C++Socket网络通信实现一个服务器端和多个客户端的通信C++Socket网络通信实现一个服务器端和多个客户端的通信标签:C++Socket但服务器对多客户端2017-04-0610:59499人阅读评论(5)收藏举报分类:C++网络通信(2)版权声明:本文为博主原创文章,未经博主允许不得转载。一描述1采用C++语言2编译环境是code::blocks3使用的是非阻塞套接字二功能描述1一个服务器对多个客户端2服务器端主要负责处理数据的输入并发送,具体是通过发送指令向其指定的客户端发送数据,发送接收指令读取其指定的客户端发送的数据3客户端的主要负责接收并发送数据,不做数据的处理三实现情况1server端2client端四server思路图五程序源码[cpp]viewplaincopyprint?#includeserver.h#include<string.h>//定义全局变量chardataBuf[MAX_NUM_BUF];//写缓冲区BOOLbConning;//与客户端的连接状态BOOLbSend;//发送标记位SOCKETsServer;//服务器监听套接字CRITICAL_SECTIONcs;//保护数据的临界区对象HANDLEhAcceptThread;//数据处理线程句柄HANDLEhRecvThread;//数据接收线程ClIENTVECTORclientvector;SVECTORstringvector;/***初始化*/BOOLInitSever(void){InitMember();//初始化全局变量//初始化SOCKETif(!InitSocket())returnFALSE;returnTRUE;}/***初始化全局变量*/voidInitMember(void){InitializeCriticalSection(&cs);//初始化临界区memset(dataBuf,0,MAX_NUM_BUF);bSend=FALSE;bConning=FALSE;//服务器为没有运行状态hAcceptThread=NULL;//设置为NULLhRecvThread=NULL;sServer=INVALID_SOCKET;//设置为无效的套接字clientvector.clear();//清空向量stringvector.clear();}/***初始化SOCKET*/boolInitSocket(void){//返回值intreVal;//初始化WindowsSocketsDLLWSADATAwsData;reVal=WSAStartup(MAKEWORD(2,2),&wsData);//创建套接字sServer=socket(AF_INET,SOCK_STREAM,0);if(INVALID_SOCKET==sServer)returnFALSE;//设置套接字非阻塞模式unsignedlongul=1;reVal=ioctlsocket(sServer,FIONBIO,(unsignedlong*)&ul);if(SOCKET_ERROR==reVal)returnFALSE;//绑定套接字sockaddr_inserAddr;serAddr.sin_family=AF_INET;serAddr.sin_port=htons(SERVERPORT);serAddr.sin_addr.S_un.S_addr=INADDR_ANY;reVal=bind(sServer,(structsockaddr*)&serAddr,sizeof(serAddr));if(SOCKET_ERROR==reVal)returnFALSE;//监听reVal=listen(sServer,SOMAXCONN);if(SOCKET_ERROR==reVal)returnFALSE;//等待客户端的连接cout<<Serversucceeded!<<endl;cout<<Waitingforclients...<<endl;returnTRUE;}/***启动服务*/boolStartService(void){BOOLreVal=TRUE;//返回值ShowTipMsg(TRUE);//提示用户输入charcInput;//输入字符do{cin>>cInput;if('s'==cInput||'S'==cInput){if(createAcceptThread())//接受客户端请求的线程{ShowServerStartMsg(TRUE);//创建线程成功信息}else{reVal=FALSE;}bSend=TRUE;break;//跳出循环体}else{ShowTipMsg(TRUE);}}while(cInput!='s'&&cInput!='S');//必须输入's'或者'S'字符returnreVal;}/***@des:createaclientrequestthread*/BOOLcreateAcceptThread(void){bConning=TRUE;//设置服务器为运行状态//创建释放资源线程unsignedlongulThreadId;//创建接收客户端请求线程hAcceptThread=CreateThread(NULL,0,AcceptThread,NULL,0,&ulThreadId);if(NULL==hAcceptThread){bConning=FALSE;returnFALSE;}else{CloseHandle(hAcceptThread);}returnTRUE;}/***接受客户端连接*/DWORD__stdcallAcceptThread(void*pParam){SOCKETsAccept;//接受客户端连接的套接字sockaddr_inaddrClient;//客户端SOCKET地址while(bConning)//服务器的状态{memset(&addrClient,0,sizeof(sockaddr_in));//初始化intlenClient=sizeof(sockaddr_in);//地址长度sAccept=accept(sServer,(sockaddr*)&addrClient,&lenClient);//接受客户请求if(INVALID_SOCKET==sAccept){Sleep(100);intnErrCode=WSAGetLastError();if(nErrCode==WSAEWOULDBLOCK)//无法立即完成一个非阻挡性套接字操作{Sleep(TIMEFOR_THREAD_SLEEP);continue;//继续等待}else{return0;//线程退出}}else//接受客户端的请求{//显示客户端的IP和端口char*pClientIP=inet_ntoa(addrClient.sin_addr);u_shortclientPort=ntohs(addrClient.sin_port);cout<<Acceptaclient.<<endl;cout<<IP:<<pClientIP<<\tPort:<<clientPort<<endl;//加入容器clientvector.push_back(sAccept);}}return0;//线程退出}/***@des:处理数据*/voidinAndOut(void){while(bConning){memset(dataBuf,0,MAX_NUM_BUF);//清空接收缓冲区cin.getline(dataBuf,MAX_NUM_BUF);//输入数据//发送数据if(bSend){handleData(dataBuf);}}}/***@des:readalinewords*//***读一行数据*/boolRecvLine(SOCKETs,char*buf){boolretVal=TRUE;//返回值boolbLineEnd=FALSE;//行结束intnReadLen=0;//读入字节数intnDataLen=0;//数据长度memset(buf,0,MAX_NUM_BUF);//清空接收缓冲区while(!bLineEnd&&bConning)//与客户端连接没有换行{nReadLen=recv(s,buf+nDataLen,1,0);//每次接收一个字节//错误处理if(SOCKET_ERROR==nReadLen){intnErrCode=WSAGetLastError();if(WSAEWOULDBLOCK==nErrCode)//接受数据缓冲区不可用{continue;//继续循环}elseif(WSAENETDOWN==nErrCode||WSAETIMEDOUT==nErrCode||WSAECONNRESET==nErrCode)//客户端关闭了连接{retVal=FALSE;//读数据失败break;//线程退出}}if(0==nReadLen){retVal=FALSE;break;}if('\n'==*(buf+nDataLen))//读取结束{bLineEnd=TRUE;bSend=TRUE;//开始发送}else{nDataLen+=nReadLen;//增加数据长度}}returnretVal;}/***读取数据*/boolrecvData(SOCKETs,char*buf){memset(buf,0,MAX_NUM_BUF);//清空接收缓冲区intnReadLen=0;//读入字节数boolbLineEnd=FALSE;//行结束BOOLretVal=TRUE;while(!bLineEnd){nReadLen=recv(s,buf,MAX_NUM_BUF,0);if(SOCKET_ERROR==nReadLen){intnErrCode=WSAGetLastError();if(WSAEWOULDBLOCK==nErrCode)//接受数据缓冲区不可用{continue;//继续循环}elseif(WSAENETDOWN==nErrCode||WSAETIMEDOUT==nErrCode||WSAECONNRESET==nErrCode)//客户端关闭了连接{retVal=FALSE;//读数据失败break;//线程退出}}if(0==nReadLen)//未读取到数据{retVal=FALSE;break;}bLineEnd=TRUE;}returnretVal;}/***@Des:senddatatoclient*/boolsendData(SOCKETs,char*str){intretVal;//返回值boolbLineEnd=FALSE;//行结束while(!bLineEnd){retVal=send(s,str,strlen(str),0);//一次发送//错误处理if(SOCKET_ERROR==retVal){intnErrCode=WSAGetLastError();//错误代码if(WSAEWOULDBLOCK==nErrCode){continue;}elseif(WSAENETDOWN==nErrCode||WSAETIMEDOUT==nErrCode||WSAECONNRESET==nErrCode){returnFALSE;}}bLineEnd=TRUE;}returnTRUE;//发送成功}/***@des:handledatatochoosewhatkindofpattern*/voidhandleData(char*str){SOCKETsClient;charcnum