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))

 

posted @ 2014-12-27 23:08  落雪成冰  阅读(1417)  评论(0编辑  收藏  举报