zoukankan      html  css  js  c++  java
  • Socket的select制作多客户端传输(Qt)

    界面用的Qt做的,制作的是一个小工具,实在是没时间,代码只是初步代码,很多Bug,估计还不能完美运行起来了。开始打算增加个内网穿透模块的,一来找不到服务器,二来工作上上最近换新框架,真的抽不出时间来,每天下班都比较累,想听下音乐放松下就洗洗睡了,各位不要见笑。

    下面上代码。初步模型呢,画了个图,方便理解,都是小东西,select是过时的东西了,并不适合真正的项目了。

    代码如下:

    Server:

    Server.h
    class ServerInit
    {
    public:
    	ServerInit(void);
    	~ServerInit(void);
    	void Init();
    	void CheckPackType(SOCKET *_socket);
    	void AddFileinfo(DataInfo _datainfo,SOCKET *_sock);
    	void SendInfo(SOCKET _sock,ServerInit *pServer);
        void ClientRegister(DataInfo *_pdata,SOCKET *_sock);
    	FD_SET * GetFD(){return &m_fd;}
    	SOCKET* GetSocket(){return &m_ServerSock;}
    	std::map<char*,ServerInfo>* GetMap(){return &m_ClientData;}
    	std::map<SOCKET,sockaddr_in> m_clientIP;
    
    private:
    	SOCKET m_ServerSock;
    	WSADATA m_ServerData;
    	SOCKADDR_IN m_ServerADDR;
    	SOCKET m_acceptClient;
    	HANDLE m_handle;
    	DWORD  m_ThreadID;
    	
    	FD_SET m_fd;
    	std::map<char*,ServerInfo>m_ClientData;
    	
    };
    

      

    Server.cpp
    
    #include "stdafx.h"
    #include "ServerInit.h"
    
    timeval g_timeout = {1,0}; //2s轮询
    
    
    
    ServerInit::ServerInit(void)
    { 
    #ifdef WIN32
    
    	int errorValue = WSAStartup(MAKEWORD(2,2),&m_ServerData);
    	if (errorValue != NO_ERROR)
    	{
    		printf("Init Error,Get Version Error");
    		return;
    	}
    
    	if(LOBYTE(m_ServerData.wVersion)!=2 || HIBYTE(m_ServerData.wVersion)!=2)
    	{
    		printf("Error,网络初始化错误");
    		return ;
    	}
    #endif
      
    	m_ServerSock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    	if(m_ServerSock == INVALID_SOCKET)
    	{
    		return;
    	}
    	m_ServerADDR.sin_family = AF_INET;
    	m_ServerADDR.sin_addr.S_un.S_addr =INADDR_ANY;
    	m_ServerADDR.sin_port = htons(SERVER_PORT);
    	if(bind(m_ServerSock,(sockaddr*)&m_ServerADDR,sizeof(m_ServerADDR))<0)
    	{ 
    		return ;
    	}
    	listen(m_ServerSock,20);
    	FD_ZERO(&m_fd);
    	FD_SET(m_ServerSock,&m_fd);
    }
    
    ServerInit::~ServerInit(void)
    {
      
    }
    
    //检测包的类型
    void ServerInit::CheckPackType(SOCKET *_socket)
    {      
    	    DataInfo *buff = new DataInfo;
    		recv(*_socket,(char*)buff,g_Packlength,NULL);
    		switch (buff->id)
    		{
    		case IsRegister: ClientRegister(buff,_socket);break;
    		case SEARCHDATA: SendInfo(_sock,pServer);break;
    		case sendFileInfo: AddFileinfo(pdata,_sock);
    			default:
    			printf("错误的数据类型== %d",pdata.id);
    				break;
    		}
    }
    
    void ServerInit::ClientRegister(DataInfo *_pdata,SOCKET *_sock)
    {   
    	DataInfo RegisterInfo;
    	std::map<SOCKET,sockaddr_in>::iterator  _clientinfo = m_clientIP.find(*_sock);
    	assert(_clientinfo != m_clientIP.end());
    	char* clientIP = inet_ntoa(_clientinfo->second.sin_addr);
        std::map<char*,ServerInfo>::iterator _iter = m_ClientData.find(clientIP);
    	if (_iter ==  m_ClientData.end())
    	{   
    		printf("新的用户,%s",clientIP);
    		RegisterInfo.id = UnKnowClient;
    		send(*_sock,(char*)&RegisterInfo,sizeof(DataInfo),NULL);
    	}
    	else
    	{
    	    RegisterInfo.id = KnowClient;
    	    send(*_sock,(char*)&RegisterInfo,sizeof(DataInfo),NULL);
    	}
    
    }
    
    void ServerInit::SendInfo(SOCKET _sock,ServerInit *pServer)
    {   
    	std::map<char*,ServerInfo>::iterator _iter =  pServer->m_ClientData.begin();
    	DataInfo _datainfo;
        for (;_iter !=  pServer->m_ClientData.end();_iter++)
        {   
    		 auto _piter = _iter->second.m_info.begin();
    		 for (;_piter != _iter->second.m_info.end();_piter++ )
    		 {   
    			 _datainfo = *_piter;
    			 send(_sock,(char*)&_datainfo,sizeof(DataInfo),NULL);
    			 _datainfo.Reset();
    		 }
    		
        }
    }
    
    void ServerInit::AddFileinfo(DataInfo _datainfo,SOCKET *_sock)
    {   
    	ServerInfo _Sinfo;
    	std::map<SOCKET,sockaddr_in>::iterator itet = m_clientIP.find(*_sock);
    	if (itet == m_clientIP.end())
    	{
    		assert(false);
    	}
    	_Sinfo.ip = inet_ntoa(itet->second.sin_addr);
    	_Sinfo.port	 = ntohs(itet->second.sin_port);
    	_Sinfo.m_info.push_back(_datainfo);
    	 m_ClientData.insert(std::make_pair(_Sinfo.ip,_Sinfo));
    }
    

      

    main:
    
    
    int g_state;
    static void ThreadNew(LPVOID lparam)
    {   
    	 ServerInit *pData =(ServerInit*)&lparam;
    	 sockaddr_in clientinfo;
         int len = sizeof(sockaddr_in);
         SOCKET NewClient = accept(*pData->GetSocket(),(sockaddr*)&clientinfo,&len);
    	 FD_SET(NewClient,pData->GetFD());
    	 pData->m_clientIP.insert(std::make_pair(NewClient,clientinfo));
    	_endthread();
    }
    
    
    
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {    
    	ServerInit app;
    	while(true)
    	{   
    		FD_SET fd_read = *app.GetFD();
    		g_state =select(*app.GetSocket()+1,&fd_read,NULL,NULL,NULL);
    		if(g_state > 0)
    		{   
    		  for (int i = 0; i<app.GetFD()->fd_count;i++)
    		  {
    			  if (FD_ISSET(app.GetFD()->fd_array[i],&fd_read))
    			  {
    				 if (app.GetFD()->fd_array[i] == *app.GetSocket())
    				 {
    					 _beginthread(ThreadNew,NULL,(void*)&app);
    				 }
    				 else
    				 {   
    					 app.CheckPackType((&)app.GetFD()->fd_array[i]);
    				 }
    			  }
    		  }
    
    
    
    
    		}
    		if (g_state == -1)
    		{
    			int erron = WSAGetLastError();
    			return -1;
    		}
    	}
    	
    	return 0;
    }
    

      

    Client:

    client.h

    class SockGUIThread : public QMainWindow
    {
    Q_OBJECT

    public:
    SockGUIThread(QWidget *parent = 0);
    ~SockGUIThread();


    int InitClient();
    int Register();
    public slots:
    void Search();

    private:
    Ui::SockGUIThreadClass ui;
    SOCKET m_sock;
    WSADATA m_data;
    int m_errorValue;
    SOCKADDR_IN addclient;
    char Type[1]; //请求搜索的类型
    DataInfo m_recvinfo;

    };

      

    client.cpp

    SockGUIThread::SockGUIThread(QWidget *parent)
    : QMainWindow(parent)
    {
    ui.setupUi(this);
    ui.m_Search->setEnabled(false);
    ui.m_progressBar->setMaximum(100);
    ui.m_progressBar->setMinimum(0);
    QObject::connect(ui.m_Search,SIGNAL(clicked()),this,SLOT(Search()));
    QObject:;connect(ui.m_close,SIGNAL(clicked()),this,SLOT(close()));
    Type[0]=1;
    if ( InitClient() < 0 )
    {
    QMessageBox::about(this,"Error","初始化失败,请尝试用管理员权限运行此程序");
    closesocket(m_sock);
    WSACleanup();
    // close();
    }

    }

    SockGUIThread::~SockGUIThread()
    {
    closesocket(m_sock);
    WSACleanup();


    }

    //第一次安装客户端,提交客户端文件信息
    int SockGUIThread::InitClient()
    {
    m_errorValue = WSAStartup(MAKEWORD(2,2),&m_data);
    if (m_errorValue != NO_ERROR)
    {
    QMessageBox::about(this,"Error","初始化网络错误13001");
    return -1;
    }


    if(LOBYTE(m_data.wVersion)!=2 || HIBYTE(m_data.wVersion)!=2)
    {
    QMessageBox::about(this,"Error","网络初始化错误13003");
    return -1;
    }


    m_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(m_sock == INVALID_SOCKET)
    {
    QMessageBox::about(this,"Error","初始化网络出错13002");
    return -1;
    }

    addclient.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);
    addclient.sin_family = AF_INET;
    addclient.sin_port = htons(SERVER_PORT);

    if (::connect(m_sock,(LPSOCKADDR)&addclient,sizeof(addclient)) < 0 )
    {
    QMessageBox::about(this,"Error","连接到服务器失败 初始化");
    return -1;
    }
    DataInfo req;
    req.id = IsRegister;
    send(m_sock,(char*)&req,g_Packlength("test"),0);
    req.Reset();
    recv(m_sock,(char*)&req,g_Packlength("test"),0);
    if(req.id == UnKnowClient)
    {
    Register();
    }

    if(req.id == KnowClient)
    {
    ui.m_Search->setEnabled(true);
    }
    return 1;
    }


    int SockGUIThread::Register()
    {
    DataInfo req;


    QString CurPath;
    QDir dir;
    CurPath = dir.currentPath();
    QStringList _StringList;
    _StringList <<QString("*.jpeg")<<QString("*.png")<<QString("*.jpg")<<QString("*.bmp")<<QString("*.rmvb")<<QString("*.avi")<<QString("*.mp4");
    dir.setFilter(QDir::Files | QDir::NoSymLinks);
    dir.setNameFilters(_StringList);
    int fileCount = dir.count();
    if(dir.count() == 0)
    {
    return EmptyFileter;
    }
    CurPath = dir.currentPath();
    QChar _char = QChar('\');
    QStringList filelist;
    for (int i=0;i<dir.count();i++)
    {
    QString file_name = dir[i];
    filelist.append(dir.currentPath() + _char + file_name);
    }
    _StringList.clear();
    _StringList<<"Name"<<"Size";
    ui.m_tableWidget->setColumnCount(2);
    // ui.m_tableWidget->setRowCount(filelist.count());

    FileInfo _info;
    for (int i=0;i < filelist.count();i++)
    {
    /* ui.m_tableWidget->setItem(i,0,new QTableWidgetItem(filelist[i]));*/
    QFile _file(filelist[i]);
    req.id = sendFileInfo;
    req.filesize = _file.size();
    req.pName =(char*)&filelist[i];
    send(m_sock,(char*)&req,g_Packlength(req.pName),NULL);
    req.Reset();
    /* ui.m_tableWidget->setItem(i,1,new QTableWidgetItem(QString::number((float)_file.size()/1000)+"kb"));*/
    }
    ui.m_Search->setEnabled(true);
    return 1;
    }

    void SockGUIThread::Search()
    {
    DataInfo m_recvinfo;
    m_recvinfo.Reset();
    m_recvinfo.id =SEARCHDATA;
    send(m_sock,(char *)&m_recvinfo,g_Packlength(m_recvinfo.pName),0);
    m_recvinfo.Reset();
    int GetLen = recv(m_sock,(char*)&m_recvinfo,4096,0);
    int _Count = ui.m_tableWidget->rowCount();
    ui.m_tableWidget->setItem(_Count+1,0,new QTableWidgetItem(m_recvinfo.pName));
    ui.m_tableWidget->setItem(_Count+1,1,new QTableWidgetItem(QString::number((float)m_recvinfo.filesize/(10*6))+"Mb"));

    }

     

    DataInfo.h
    
    
    #include <list>
    #include <map>
    #include <memory.h>
    #define  MAX_ARRAY 1024
    #define  SERVER_IP "127.0.0.1"
    #define  SERVER_PORT 5656
    #define  KnowClient 1
    #define  UnKnowClient 3
    #define  IsRegister 2
    #define  RequestFileInfo 10
    #define  sendFileInfo    11
    #define  EmptyFileter    20
    #define  SEND_ERROR      -5
    #define  SEARCHDATA     30
    
    struct FileInfo
    {
    	long filesize;
    	char *pName;
    
    };
    
    
    //连接服务端数据类型
    struct DataInfo
    {
    	int id; //id 请求类型
    	long filesize;
    	char *pName;
    	void Reset()
    	{
    		id =NULL;
    		filesize =NULL;
    		pName =NULL;
    
    	}
    	
    };
    
    struct ServerInfo
    {
    	char *ip;
    	int port;
    	std::list<DataInfo> m_info;
    };
    #define  g_Packlength(str)  (sizeof(DataInfo)+strlen(str))
    

     

  • 相关阅读:
    SQL Server 使用全文索引进行页面搜索
    基于TI Davinci架构的多核/双核开发高速扫盲(以OMAP L138为例),dm8168多核开发參考以及达芬奇系列资料user guide整理
    HBase 数据库检索性能优化策略
    在oracle存储过程中创建暂时表
    永和维护---从问题中得到的一些感受
    spring set注入
    为计算机教育改革而摇旗呐喊
    hdu5288 OO’s Sequence 二分 多校联合第一场
    HTML5贪吃蛇源代码
    软工初体验
  • 原文地址:https://www.cnblogs.com/dragonmoon/p/4189374.html
Copyright © 2011-2022 走看看