当前位置: 首页 > news >正文

哪个网站做淘宝客视频下载网站软件做副屏

哪个网站做淘宝客,视频下载网站软件做副屏,wordpress底部 社交,猎聘网招聘官方网站Windows socket之最简单的socket程序 原文:Windows socket之最简单的socket程序 最简单的服务器的socket程序流程如下(面向连接的TCP连接 ): 1. WSAStartup(); 初始化网络库的使用。 2. socket(); 获得一个socket。 3. bind(); 把获得的socket绑定到一个ip 和端口。既然作为服务… Windows socket之最简单的socket程序 原文:Windows socket之最简单的socket程序 最简单的服务器的socket程序流程如下(面向连接的TCP连接 ): 1. WSAStartup(); 初始化网络库的使用。 2. socket(); 获得一个socket。 3. bind(); 把获得的socket绑定到一个ip 和端口。既然作为服务器, ip通常为本地IP127.0.0.1。 4. listen(); 监听已经绑定了指定端口的socket。 5. accept(); 接受一个来自客户端的连接。 accept()返回一个新的socket,该socket代表着本地服务器与某一个连接过来的客户端的链接。以该socket为参数可以调用send函数往客户端发送数据也可以调用recv函数接受客户端发送过来的函数。 最后服务器程序结束的时候调用closesocket()关闭socket, WSACleanup()终止网络库的使用清理资源。 最简单的客户端的socket程序流程如下(同样是面向连接的TCP连接): 1. WSAStartup();初始化网络库的使用。 2. socket(); 获得一个socket。 3. connect(); 连接到一个 服务器。 连接成功后就可以收发数据了。收发完毕后调用closesocket()关闭socket,最后程序结束前调用 WSACleanup()清理资源。 下面直接上代码 需包含以下头文件和定义 #include stdlib.h #include stdio.h #include WinSock2.h #pragma comment(lib,ws2_32.lib) #define SERVE_ADDRESS 127.0.0.1 #define SERVE_PORT    7001 // ---------------------------- WSAStartup() ----------------------------//WSADATA wsd;int resStartup WSAStartup(MAKEWORD(2,2),wsd);if(0 ! resStartup){printf(failed to WSAStartup!\n);goto Main_End;}//------------------------------------------------------------------------------//// ---------------------------- socket() ----------------------------//SOCKET serverSocket socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(INVALID_SOCKET serverSocket){printf(failed to invoke socket, the socket returned is invalid!\n);goto Main_End;}// ------------------------------------------------------------------------------------////---------------------------- bind() ----------------------------//// 初始化 struct sockaddr 结构体 SOCKADDR_IN就是 struct sockaddr的宏定义SOCKADDR_IN localAddr;localAddr.sin_family AF_INET;localAddr.sin_addr.S_un.S_addr inet_addr(SERVE_ADDRESS); localAddr.sin_port htons(SERVE_PORT); memset(localAddr.sin_zero,0x0,sizeof(localAddr.sin_zero));// int resBind bind(serverSocket,(sockaddr*)localAddr,sizeof(SOCKADDR_IN));if(0 ! resBind){printf(failed to bind ! \n);goto Main_End;}//------------------------------------------------------------------------------------////---------------------------- listen() ----------------------------//int resListen listen(serverSocket,5);if(0 ! resListen){printf(failed to listen! \n);goto Main_End;}printf(the server is listening now!\n);//------------------------------------------------------------------------------------////---------------------------- accept() ----------------------------//SOCKADDR_IN clientAddr;int addrLen sizeof(clientAddr);SOCKET acceptedSocket accept(serverSocket,(sockaddr*)clientAddr,addrLen);if(INVALID_SOCKET acceptedSocket){printf(accept error!\n);goto Main_End;}printf(a client has connected to the server!\n);//------------------------------------------------------------------------------------//char recvBuffer[256];char sendBuffer[256];strcpy(sendBuffer,server:Welcome to connect !);int sendBufLen strlen(sendBuffer);int resSend send(acceptedSocket,sendBuffer,sendBufLen,0);while(true){if(resSend ! sendBufLen) //发送的长度与需要发送的长度不等{printf(send data error!!\n);break;}int recvLen recv(acceptedSocket,recvBuffer,sizeof(recvBuffer),0);if(0 recvLen){printf(a client close the socket!\n);break;}else if(recvLen 0){printf(an error has happen when receiving\n);break;}recvBuffer[recvLen] \0;printf(client:%s\n,recvBuffer);//在客户发过来的数据前面加上server:再发回给客户端strcpy(sendBuffer,server:);strcat(sendBuffer,recvBuffer);sendBufLen strlen(sendBuffer);resSend send(acceptedSocket,sendBuffer,sendBufLen,0);}closesocket(acceptedSocket);closesocket(serverSocket);Main_End:WSACleanup();system(pause);return 0; 客户端代码 //---------------------------- WSAStartup() ----------------------------//WSADATA wsd;int resStartup WSAStartup(MAKEWORD(2,2),wsd);if(0 ! resStartup){printf(failed to WSAStartup!\n);goto Main_End;}//------------------------------------------------------------------------------------////---------------------------- socket() ----------------------------//SOCKET connSocket socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(INVALID_SOCKET connSocket){printf(the socket returned is invalid!\n);goto Main_End;}//------------------------------------------------------------------------------------////---------------------------- connect() ----------------------------////初始化struct sockaddr 结构体 SOCKADDR_IN serverAddr;serverAddr.sin_family AF_INET;serverAddr.sin_addr.S_un.S_addr inet_addr(SERVE_ADDRESS);serverAddr.sin_port htons(SERVE_PORT);memset(serverAddr.sin_zero,0x0,sizeof(serverAddr.sin_zero));//connectint resConn connect(connSocket,(sockaddr*)serverAddr,sizeof(serverAddr));if(0 ! resConn){printf(failed to connect to server!!\n);goto Main_End;}//------------------------------------------------------------------------------------//char sendBuffer[256];char recvBuffer[256];while(true){int recvLen recv(connSocket,recvBuffer,256,0);if(recvLen 0){printf(receive error!!\n);break;}else if(0 recvLen){printf(the server close the socket!\n);}recvBuffer[recvLen] \0;printf(the data recv:%s\n\n\n,recvBuffer);printf(please input what you want to send:\n);gets(sendBuffer);if(0 strcmp(sendBuffer,exit)){break;}int sendDataLen strlen(sendBuffer);int nDataSent send(connSocket,sendBuffer,sendDataLen,0);if(nDataSent ! sendDataLen){printf(failed to send data!!\n);break;}}closesocket(connSocket);printf(the connection is closed!\n);Main_End:WSACleanup();system(pause);return 0; 客户端连接到服务端后每次给服务端发送一段内容服务器在内容前面加上server:再发送给客户端。 当客户端发送的内容是exit时客户端程序跳出循环关闭socket断开连接。服务端发现客户端断开连接后也关闭套接字结束程序。 当然上面程序只为了演示最简单的网络编程。有若干漏洞。 1. 服务器只能接受一个客户端连接。当然加一个循环语句进去可以重复地接受客户端的连接但是仍然是每次只处理一个客户端连接。 2.accept, connect,send,recv函数默认均是阻塞函数。当没有客户连接到服务端时服务端阻塞在accept函数无法退出程序。当服务器在接受客户端的数据时如果客户端不发送数据也不断开连接那么服务端阻塞在recv函数无法退出程序。 改进该程序使得服务端随时都可以停止服务退出程序无论有多少个用户已经在连接。 为了多个客户端可以同时连接最容易理解的便是利用多线程。每一个连接的客户端都用一个线程去处理它的通信。 至于为了随时可以退出服务端不能再调用永久阻塞的函数了。利用select函数可以阻塞指定的时间阻塞期间不占CPU。 int select( __in int nfds, __in_out fd_set*readfds, __in_out fd_set*writefds, __in_out fd_set*exceptfds, __in const struct timeval*timeout); nfds 用于兼容Berkeley sockets.不用理会随便给个0值就OK。 readfds 用于检查是否存在可读socket的的一个socket集合。可为空。 writefds 用于检查是否存在可写socket的一个socket集合。可为空。 exceptfds 用于检查是否存在有错误的socket的一个 socket集合可为空。 timeout TIMEVAL结构体用于指定该函数阻塞多长时间。 在 调用select时当readfds不为空时当readfds中任何一个socket就绪可读时或者当writefds不为空且writefds中任何一个socket准备就绪可写或者当exceptfds不为空且任何一个socket发生socket错误时select就立即返回。否则直到timeout指定的时间过去以后才返回。 返回值返回准备就绪的socket的个数。如果为0说明该函数超时了如果大于0说明至少有一个socket就绪。如果小于0说明发生错误了。 fd_set 是一种集合类型。 typedef struct fd_set {         u_int fd_count;               /* how many are SET? */         SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */ } fd_set; 记录着一个socket数组以及里面的socket个数。 struct timeval是一个表示等待时间的结构体。 struct timeval {         long    tv_sec;         /* seconds */         long    tv_usec;        /* and microseconds */ }; tv_sec表示有多少秒tv_usec表示有多少毫秒。 对于fd_set类型用到几个宏定义函数。 FD_ZERO(fd_set*), 清空fd_set集合 FD_SET(SOCKET,fd_set*),把socket加入fd_set集合。 FD_ISSET(SOCKET,fd_set*),判断socket是否在集合fd_set中并且socket准备就绪。 FD_CLR(SOCKET,fd_set*),如果fd_set存在该SOCKET则移除它。 下面是改进后的服务端代码 typedef struct _ThreadInfo {HANDLE hThread;bool bRunning;SOCKET sock; }ThreadInfo;typedef struct _AcceptThreadParam {bool bRunning;SOCKET listeningSocket; }AcceptThreadParam;std::listThreadInfo* g_threadInfoList; CRITICAL_SECTION g_csForList;DWORD WINAPI ListeningThread(LPVOID lpParameter); DWORD WINAPI CommunicationThread(LPVOID lpParameter);int _tmain(int argc, _TCHAR* argv[]) {_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);// ---------------------------- WSAStartup() ----------------------------//WSADATA wsd;int resStartup WSAStartup(MAKEWORD(2,2),wsd);if(0 ! resStartup){printf(failed to WSAStartup!\n);return -1;}//------------------------------------------------------------------------------//InitializeCriticalSection(g_csForList);// ---------------------------- socket() ----------------------------//SOCKET serverSocket socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(INVALID_SOCKET serverSocket){printf(failed to invoke socket, the socket returned is invalid!\n);goto Main_End;}// ------------------------------------------------------------------------------------////---------------------------- bind() ----------------------------//// 初始化 struct sockaddr 结构体 SOCKADDR_IN就是 struct sockaddr的宏定义SOCKADDR_IN localAddr;localAddr.sin_family AF_INET;localAddr.sin_addr.S_un.S_addr inet_addr(SERVE_ADDRESS); localAddr.sin_port htons(SERVE_PORT); memset(localAddr.sin_zero,0x0,sizeof(localAddr.sin_zero));// int resBind bind(serverSocket,(sockaddr*)localAddr,sizeof(SOCKADDR_IN));if(0 ! resBind){printf(failed to bind ! \n);goto Main_End;}//------------------------------------------------------------------------------------////---------------------------- listen() ----------------------------//int resListen listen(serverSocket,5);if(0 ! resListen){printf(failed to listen! \n);goto Main_End;}//------------------------------------------------------------------------------------//AcceptThreadParam threadParam;threadParam.bRunning true;threadParam.listeningSocket serverSocket;HANDLE hListeningThread CreateThread(0,0,ListeningThread,threadParam,0,0);if(0 hListeningThread){printf(failed to create the listening thread!\n);goto Main_End;}else{printf(the server is listening now!pass any key to close the server!\n);}while(true){char ch getchar();threadParam.bRunning false;DWORD resWait WaitForSingleObject(hListeningThread,3000);if(WAIT_TIMEOUT resWait){printf(failed to wait for the listening thread exiting!\n);}else{printf(the listening thread has exited!\n);}break;}Main_End:if(INVALID_SOCKET ! serverSocket){closesocket(serverSocket);serverSocket INVALID_SOCKET;}WSACleanup();DeleteCriticalSection(g_csForList);system(pause);return 0; }DWORD WINAPI ListeningThread(LPVOID lpParameter) {AcceptThreadParam* pAcceptThreadParam (AcceptThreadParam*)lpParameter;SOCKET serverSocket pAcceptThreadParam-listeningSocket;while(pAcceptThreadParam-bRunning){//---------------------------- accept() ----------------------------//fd_set fdAccept;FD_ZERO(fdAccept);FD_SET(serverSocket,fdAccept);TIMEVAL acceptTimeVal;acceptTimeVal.tv_sec 1;acceptTimeVal.tv_usec 0;int selRes select(0,fdAccept,0,0,acceptTimeVal);if(selRes 0){SOCKADDR_IN clientAddr;int addrLen sizeof(clientAddr);SOCKET acceptedSocket accept(serverSocket,(sockaddr*)clientAddr,addrLen);if(INVALID_SOCKET acceptedSocket){printf(accept error!\n);break;}printf(a client has connected to the server!\n);ThreadInfo* pTI new ThreadInfo;pTI-bRunning true;pTI-sock acceptedSocket;pTI-hThread CreateThread(0,0,CommunicationThread,(LPVOID)pTI,0,0);if(0 pTI-hThread){printf(failed to create a thread!\n);delete pTI;pTI 0;}else{EnterCriticalSection(g_csForList);g_threadInfoList.push_back(pTI);LeaveCriticalSection(g_csForList);}}else if(selRes 0){printf(an error has occured when listening !\n);break;}}std::listThreadInfo* tempList;EnterCriticalSection(g_csForList);std::listThreadInfo*::iterator listIter;for(listIter g_threadInfoList.begin(); listIter ! g_threadInfoList.end(); listIter){(*listIter)-bRunning false;tempList.push_back(*listIter);}g_threadInfoList.clear();LeaveCriticalSection(g_csForList);int nSuccessfullyExit 0;for(listIter tempList.begin(); listIter ! tempList.end(); listIter){DWORD resWait WaitForSingleObject((*listIter)-hThread,2000);if(WAIT_TIMEOUT resWait){printf(failed to wait for a communication thread exiting!\n);}else{nSuccessfullyExit;}delete (*listIter);}printf(succeed waiting for %d thread exiting!\n,nSuccessfullyExit);tempList.clear();printf(listening thread is exiting!\n);return 0; }DWORD WINAPI CommunicationThread(LPVOID lpParameter) {ThreadInfo* pThreadInfo (ThreadInfo*)lpParameter;SOCKET clientSocket pThreadInfo-sock;fd_set fdRead,fdWrite;FD_ZERO(fdRead);FD_ZERO(fdWrite);FD_SET(clientSocket,fdRead);FD_SET(clientSocket,fdWrite);TIMEVAL sendTimeVal;sendTimeVal.tv_sec 0;sendTimeVal.tv_usec 500;int selRes select(0,0,fdWrite,0,sendTimeVal);if(selRes 0){goto ThreadOver;}char recvBuffer[256];char sendBuffer[256];strcpy(sendBuffer,server:Welcome to connect !);int sendBufLen strlen(sendBuffer);int resSend send(clientSocket,sendBuffer,sendBufLen,0);if(resSend ! sendBufLen){printf(there are %d bytes to send, but it just succeeded sending %d bytes!\n,sendBufLen,resSend);goto ThreadOver;}while(pThreadInfo-bRunning){ FD_ZERO(fdRead);FD_SET(pThreadInfo-sock,fdRead);TIMEVAL recvTimeVal;recvTimeVal.tv_sec 0;recvTimeVal.tv_usec 500;int recvSelRes select(0,fdRead,0,0,recvTimeVal);if(recvSelRes 0){printf(socket error when receiving!\n);break;}else if(recvSelRes 0){int recvLen recv(clientSocket,recvBuffer,sizeof(recvBuffer),0);if(0 recvLen){printf(a client close the socket!\n);break;}else if(recvLen 0){printf(an error has happen when recving\n);break;}else{recvBuffer[recvLen] \0;printf(a client:%s\n,recvBuffer);strcpy(sendBuffer,server:);strcat(sendBuffer,recvBuffer);sendBufLen strlen(sendBuffer);FD_ZERO(fdWrite);FD_SET(pThreadInfo-sock,fdWrite);sendTimeVal.tv_sec 0;sendTimeVal.tv_usec 500;int sendSelRes select(0,0,fdWrite,0,sendTimeVal);if(sendSelRes 0){int bytesSent send(clientSocket,sendBuffer,sendBufLen,0);if(bytesSent ! sendBufLen){printf(there are %d bytes to be sent,but only %d bytes are sent!\n,sendBufLen,bytesSent);break;}}else{printf(failed to send in 500 ms!\n);break;}}}}ThreadOver:closesocket(pThreadInfo-sock);bool bMainThreadWaiting true;EnterCriticalSection(g_csForList);std::listThreadInfo*::iterator listIter;for(listIter g_threadInfoList.begin(); listIter ! g_threadInfoList.end(); listIter){if(pThreadInfo (*listIter)){bMainThreadWaiting false;g_threadInfoList.erase(listIter);break;}}LeaveCriticalSection(g_csForList);if(false bMainThreadWaiting){CloseHandle(pThreadInfo-hThread);delete pThreadInfo;pThreadInfo 0;}return 0; } 前面的代码与之前的一样改变的地方在于accept的地方。对于一个监听的socket,如果该socket可读说明有用户连接过来了。 全局维护了一个纪录创建的线程的信息的链表每创建一个线程都有一个标识该线程是否应该继续循环执行的bool变量。当bRunning变为false的时候线程函数跳出循环返回。 当需要停止服务端运行时服务端只需要按任何一个键和回车就会通知线程退出并且调用WaitForSingleObject(),来确认线程已退出。还有利用了 EnterCriticalSection()和LeaveCriticalSection()临界区函数来保证只有一个线程在操作全局的链表。 使用多线程要消耗一定的资源。对于fd_set默认最多可以容纳64个socket.所以可以用1个线程去处理64个客户端的连接。而不必每个客户端都创建一个线程。 代码如下 typedef struct _AcceptThreadParam {bool bRunning;SOCKET listeningSocket; }AcceptThreadParam;#define SOCKET_ARRAY_SIZE 64SOCKET g_socketArray[SOCKET_ARRAY_SIZE]; int g_socketCount 0; CRITICAL_SECTION g_csForSocketArray;DWORD WINAPI ListeningThread(LPVOID lpParameter); DWORD WINAPI CommunicationThread(LPVOID lpParameter);int _tmain(int argc, _TCHAR* argv[]) {_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);// ---------------------------- WSAStartup() ----------------------------//WSADATA wsd;int resStartup WSAStartup(MAKEWORD(2,2),wsd);if(0 ! resStartup){printf(failed to WSAStartup!\n);return -1;}//------------------------------------------------------------------------------//InitializeCriticalSection(g_csForSocketArray);g_socketCount 0;// ---------------------------- socket() ----------------------------//SOCKET serverSocket socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(INVALID_SOCKET serverSocket){printf(failed to invoke socket, the socket returned is invalid!\n);goto Main_End;}// ------------------------------------------------------------------------------------////---------------------------- bind() ----------------------------//// 初始化 struct sockaddr 结构体 SOCKADDR_IN就是 struct sockaddr的宏定义SOCKADDR_IN localAddr;localAddr.sin_family AF_INET;localAddr.sin_addr.S_un.S_addr inet_addr(SERVE_ADDRESS); localAddr.sin_port htons(SERVE_PORT); memset(localAddr.sin_zero,0x0,sizeof(localAddr.sin_zero));// int resBind bind(serverSocket,(sockaddr*)localAddr,sizeof(SOCKADDR_IN));if(0 ! resBind){printf(failed to bind ! \n);goto Main_End;}//------------------------------------------------------------------------------------////---------------------------- listen() ----------------------------//int resListen listen(serverSocket,5);if(0 ! resListen){printf(failed to listen! \n);goto Main_End;}//------------------------------------------------------------------------------------//AcceptThreadParam threadParam;threadParam.bRunning true;threadParam.listeningSocket serverSocket;bool bCommunicationThreadRunning true;HANDLE hListeningThread CreateThread(0,0,ListeningThread,threadParam,0,0);HANDLE hCommunicationThread CreateThread(0,0,CommunicationThread,bCommunicationThreadRunning,0,0);if(0 hListeningThread || 0 hCommunicationThread){printf(failed to create a thread!\n);if(0 ! hListeningThread){threadParam.bRunning false;WaitForSingleObject(hListeningThread,2000);CloseHandle(hListeningThread);}if(0 ! hCommunicationThread){bCommunicationThreadRunning false;WaitForSingleObject(hCommunicationThread,2000);CloseHandle(hCommunicationThread);}goto Main_End;}else{printf(the server is listening now!pass any key to close the server!\n);}while(true){char ch getchar();threadParam.bRunning false;bCommunicationThreadRunning false;DWORD resWait WaitForSingleObject(hListeningThread,3000);if(WAIT_TIMEOUT resWait){printf(failed to wait for the listening thread exiting!\n);}else{printf(the listening thread has exited!\n);}CloseHandle(hListeningThread);resWait WaitForSingleObject(hCommunicationThread,3000);if(WAIT_TIMEOUT resWait){printf(failed to wait for the communication thread exiting!\n);}else{printf(the communication thread has exited!\n);}CloseHandle(hCommunicationThread);break;}Main_End:if(INVALID_SOCKET ! serverSocket){closesocket(serverSocket);serverSocket INVALID_SOCKET;}WSACleanup();DeleteCriticalSection(g_csForSocketArray);system(pause);return 0; }DWORD WINAPI ListeningThread(LPVOID lpParameter) {AcceptThreadParam* pAcceptThreadParam (AcceptThreadParam*)lpParameter;SOCKET serverSocket pAcceptThreadParam-listeningSocket;while(pAcceptThreadParam-bRunning){//---------------------------- accept() ----------------------------//fd_set fdAccept;FD_ZERO(fdAccept);FD_SET(serverSocket,fdAccept);TIMEVAL acceptTimeVal;acceptTimeVal.tv_sec 1;acceptTimeVal.tv_usec 0;int selRes select(0,fdAccept,0,0,acceptTimeVal);if(selRes 0){SOCKADDR_IN clientAddr;int addrLen sizeof(clientAddr);SOCKET acceptedSocket accept(serverSocket,(sockaddr*)clientAddr,addrLen);if(INVALID_SOCKET acceptedSocket){printf(accept error!\n);break;}printf(a client has connected to the server!\n);fd_set fdWrite;FD_ZERO(fdWrite);FD_SET(acceptedSocket,fdWrite);TIMEVAL writeTimeVal;writeTimeVal.tv_sec 0;writeTimeVal.tv_usec 500;int writeSelRes select(0,0,fdWrite,0,writeTimeVal);if(writeSelRes 0){int sendBufferLen strlen(server:Welcome to connect!);int bytesSent send(acceptedSocket,server:Welcome to connect!,sendBufferLen,0);if(bytesSent sendBufferLen){EnterCriticalSection(g_csForSocketArray);if(g_socketCount 64){g_socketArray[g_socketCount] acceptedSocket;g_socketCount;}else{printf(the server has accepted more than 64 clients!\n);closesocket(acceptedSocket);}LeaveCriticalSection(g_csForSocketArray);}else{printf(send error, there are %d bytes to be sent, but only %d bytes are sent!\n,sendBufferLen,bytesSent);closesocket(acceptedSocket);}}else{printf(select error of can not wait for sending data when select!\n);closesocket(acceptedSocket);}}else if(selRes 0){printf(an error has occured when listening !\n);break;}}printf(listening thread is exiting!\n);return 0; }DWORD WINAPI CommunicationThread(LPVOID lpParameter) {bool* pBRunning (bool*)lpParameter;char recvBuffer[256];char tempBuffer[256];while(true *pBRunning){int currentSocketCount 0;EnterCriticalSection(g_csForSocketArray);if(0 g_socketCount){LeaveCriticalSection(g_csForSocketArray);Sleep(200);continue;}currentSocketCount g_socketCount;LeaveCriticalSection(g_csForSocketArray);fd_set fdRead;FD_ZERO(fdRead);for(int i 0; i currentSocketCount; i){FD_SET(g_socketArray[i],fdRead);}TIMEVAL readTimeVal;readTimeVal.tv_sec 1;readTimeVal.tv_usec 0;int selRes select(0,fdRead,0,0,readTimeVal);if(selRes 0){for(int i 0; i currentSocketCount; i){if(FD_ISSET(g_socketArray[i],fdRead) ! 0){int bytesRecv recv(g_socketArray[i],recvBuffer,sizeof(recvBuffer),0);if(bytesRecv 0){recvBuffer[bytesRecv] \0;printf(the %d client: %s\n,i 1,recvBuffer);sprintf(tempBuffer,the server:%s,recvBuffer);fd_set fdWrite;FD_ZERO(fdWrite);FD_SET(g_socketArray[i],fdWrite);TIMEVAL writeTimeVal;writeTimeVal.tv_sec 0;writeTimeVal.tv_usec 500;int writeSelRes select(g_socketArray[i],0,fdWrite,0,writeTimeVal);if(writeSelRes 0){int sendBufLen strlen(tempBuffer);int bytesSent send(g_socketArray[i],tempBuffer,sendBufLen,0);if(bytesSent sendBufLen){break;}else{printf(there are %d bytes to be sent,but only %d bytes are sent!\n,sendBufLen,bytesSent);}}else{printf(select error!\n);}}else if(0 bytesRecv){printf(the %d client has closed the socket!\n,i 1);}else{printf(recv error!\n);}closesocket(g_socketArray[i]);EnterCriticalSection(g_csForSocketArray);g_socketArray[i] g_socketArray[g_socketCount - 1];g_socketCount--;LeaveCriticalSection(g_csForSocketArray);}}}else if(selRes 0){printf(select error in communication thread!\n);}}EnterCriticalSection(g_csForSocketArray);for(int i 0; i g_socketCount; i){closesocket(g_socketArray[i]);}LeaveCriticalSection(g_csForSocketArray);printf(the communication thread is exiting!\n);return 0; } 完成的功能一样。只需要一个线程就可以处理多个客户端了。 还可以用异步IO来实现该服务器以下是用完成端口来实现同样功能的服务器。 typedef struct _RepeatAcceptingThreadParam {SOCKET listeningSocket;bool* pBRunning; }RepeatAcceptingThreadParam;typedef struct _CompletionPortWorkerThreadParam {HANDLE hCompletionPort;bool* pBRunning; }CompletionPortWorkerThreadParam;#define MESSAGE_BUF_SIZE 1024enum OPERATION_TYPE {OPERATION_SEND,OPERATION_RECV };typedef struct {SOCKET sock;WSAOVERLAPPED overlap;WSABUF wsaBuf;char message[1024];DWORD bytesRecv;DWORD flags;OPERATION_TYPE operationType; }PER_IO_OPERATION_DATA;//global vector, which saves the information of the client sockets connected to the server std::vectorPER_IO_OPERATION_DATA* g_perIoDataPointerVec;//accept sockets connected to the servers listening socket in a recycle - while DWORD WINAPI RepeatAcceptingThread(LPVOID lpParameter); //the worker thread that deal with the communications between the server and the clients. DWORD WINAPI CompletionPortWorkerThread(LPVOID lpParameter);int _tmain(int argc,_TCHAR* argv[]) {_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);// ---------------------------- WSAStartup() ----------------------------//WSADATA wsd;int resStartup WSAStartup(MAKEWORD(2,2),wsd);if(0 ! resStartup){printf(failed to WSAStartup!\n);return -1;}//------------------------------------------------------------------------------//// ---------------------------- socket() ----------------------------//SOCKET serverSocket socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(INVALID_SOCKET serverSocket){printf(failed to invoke socket, the socket returned is invalid!\n);return -1;}// ------------------------------------------------------------------------------------////---------------------------- bind() ----------------------------//// 初始化 struct sockaddr 结构体 SOCKADDR_IN就是 struct sockaddr的宏定义SOCKADDR_IN localAddr;localAddr.sin_family AF_INET;localAddr.sin_addr.S_un.S_addr inet_addr(SERVE_ADDRESS); localAddr.sin_port htons(SERVE_PORT); memset(localAddr.sin_zero,0x0,sizeof(localAddr.sin_zero));// int resBind bind(serverSocket,(sockaddr*)localAddr,sizeof(SOCKADDR_IN));if(0 ! resBind){printf(failed to bind ! \n);closesocket(serverSocket);return -1;}//------------------------------------------------------------------------------------////---------------------------- listen() ----------------------------//int resListen listen(serverSocket,5);if(0 ! resListen){printf(failed to listen! \n);closesocket(serverSocket);return -1;}//------------------------------------------------------------------------------------//bool bRepeatAcceptingThreadRunning true; // a bool variable that take control of terminating the RepeatAcceptingThread.//init the parameter for the RepeatAcceptingThread.RepeatAcceptingThreadParam rtp;rtp.listeningSocket serverSocket;rtp.pBRunning bRepeatAcceptingThreadRunning;HANDLE hRepeatAcceptingThread CreateThread(0,0,RepeatAcceptingThread,rtp,0,0);if(0 hRepeatAcceptingThread){printf(failed to create the repeat-accepting thread!\n);closesocket(serverSocket);return -1;}printf(the repeat-accepting thread has run!\n);while(true){// pass any key char ch getchar();bRepeatAcceptingThreadRunning false;//to notify the RepeatAcceptingThread to exit safely DWORD waitRes WaitForSingleObject(hRepeatAcceptingThread,3000);if(WAIT_TIMEOUT waitRes){printf(failed to wait for the repeatAcceptingThread exiting!\n);}else{printf(the repeat accepting thread has exited!\n);}CloseHandle(hRepeatAcceptingThread);break;}system(pause);return 0; }DWORD WINAPI RepeatAcceptingThread(LPVOID lpParameter) {//get the parameters passed by the creator of the thread.RepeatAcceptingThreadParam* pParam (RepeatAcceptingThreadParam*)lpParameter;SOCKET listeningSocket pParam-listeningSocket;bool* pStillRun pParam-pBRunning;// create a completion portHANDLE hCompletionPort CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);if(0 hCompletionPort){printf(failed to CreateIoCompletionPort!\n);return -1;}// a bool variable for notifying the worker threads of exiting.bool bWorkThreadRunning true;// a vector of HANDLEs,which will be used for synchronization of waiting the worker threads to exit.std::vectorHANDLE threadHandlesVec;SYSTEM_INFO systemInfo;GetSystemInfo(systemInfo);//the parameter to be passed to the worker thread.CompletionPortWorkerThreadParam cpwtp;cpwtp.pBRunning bWorkThreadRunning;cpwtp.hCompletionPort hCompletionPort;for(int i 0; i systemInfo.dwNumberOfProcessors; i){HANDLE hThread CreateThread(0,0,CompletionPortWorkerThread,cpwtp,0,0);if(0 hThread) {printf(failed to create a completion port worker thread!\n);bWorkThreadRunning false;// terminate all threads created safely.std::vectorHANDLE::iterator vecIter;for(vecIter threadHandlesVec.begin(); vecIter ! threadHandlesVec.end(); vecIter){DWORD waitRes WaitForSingleObject(*vecIter,2000);if(WAIT_TIMEOUT waitRes){printf(failed the wait for the completion port worker thread!\n);}CloseHandle(*vecIter);}threadHandlesVec.clear();CloseHandle(hCompletionPort);return -1;}else{threadHandlesVec.push_back(hThread); //add the handle to the vector}}printf(succeed creating completion port worker threads!\n);while(true *pStillRun){fd_set fdAccept;FD_ZERO(fdAccept);FD_SET(listeningSocket,fdAccept);TIMEVAL acceptTimeVal;acceptTimeVal.tv_sec 1;acceptTimeVal.tv_usec 0;int selRes select(0,fdAccept,0,0,acceptTimeVal);if(selRes 0) // a client connected{SOCKADDR_IN clientAddr;int addrLen sizeof(clientAddr);SOCKET acceptedSocket WSAAccept(listeningSocket,(struct sockaddr*)clientAddr,addrLen,0,0);if(0 acceptedSocket){printf(failed to accept a connection!\n);}else{printf(a clent %s:%d has connected!\n,inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));PER_IO_OPERATION_DATA* perIoData new PER_IO_OPERATION_DATA;if(0 perIoData){closesocket(acceptedSocket);printf(failed to new a struct! there is not enough memory!\n\n);}else{//associate the newly connected client socket with the completion port.if(0 CreateIoCompletionPort((HANDLE)acceptedSocket,hCompletionPort,(ULONG_PTR)perIoData,0)){printf(failed to associate the newly connected client socket with the completion port!\n);closesocket(acceptedSocket);delete perIoData;perIoData 0;}else{//associated successfully, Set the information of the client socket in A PER_IO_OPERATION_DATA struct.//when a IO operation is completed, we can get notified with the struct to be one of the parameters.perIoData-sock acceptedSocket;perIoData-operationType OPERATION_SEND;perIoData-wsaBuf.buf perIoData-message;perIoData-overlap.hEvent INVALID_HANDLE_VALUE;strcpy(perIoData-message,Welcome to connect to the server!);perIoData-wsaBuf.len strlen(perIoData-message);int sendRes WSASend(acceptedSocket,(perIoData-wsaBuf),1,(perIoData-bytesRecv),0,0,0);if(0 sendRes) //finished immediately{// asynchronously invoke a receive operation. When the reception finished,we can get its information by// invoking GetQueuedCompletionStatus()perIoData-wsaBuf.buf perIoData-message;perIoData-wsaBuf.len MESSAGE_BUF_SIZE;perIoData-flags 0;perIoData-operationType OPERATION_RECV;ZeroMemory(perIoData-overlap,sizeof(perIoData-overlap));int recvRes WSARecv(acceptedSocket,perIoData-wsaBuf,1,perIoData-bytesRecv,perIoData-flags,perIoData-overlap,0);if(0 recvRes) //the receiving operation finished immediately , the information of the operation has been queued.{g_perIoDataPointerVec.push_back(perIoData);}else if(SOCKET_ERROR recvRes WSA_IO_PENDING WSAGetLastError()) //the receiving operation will finish later{g_perIoDataPointerVec.push_back(perIoData);}else{printf(failed to WSARecv!\n);closesocket(acceptedSocket);delete perIoData;perIoData 0;}}else if(SOCKET_ERROR sendRes WSA_IO_PENDING WSAGetLastError()) //the sending operation will finish later{g_perIoDataPointerVec.push_back(perIoData);}else{//int lastErr WSAGetLastError();printf(send data error!\n);closesocket(acceptedSocket);delete perIoData;perIoData 0;}}}}}else if(selRes 0){printf(select error!\n);}}bWorkThreadRunning false; //notifies the worker threads of exiting// terminate all threads created safely.std::vectorHANDLE::iterator vecIter;for(vecIter threadHandlesVec.begin(); vecIter ! threadHandlesVec.end(); vecIter){DWORD waitRes WaitForSingleObject(*vecIter,2000);if(WAIT_TIMEOUT waitRes){printf(failed the wait for the completion port worker thread!\n);}CloseHandle(*vecIter);}threadHandlesVec.clear();CloseHandle(hCompletionPort);//delete the structs of PER_IO_OPERATION_DATA newed for clients connected.std::vectorPER_IO_OPERATION_DATA*::iterator pIoDataPointerIter;for(pIoDataPointerIter g_perIoDataPointerVec.begin(); pIoDataPointerIter ! g_perIoDataPointerVec.end(); pIoDataPointerIter){closesocket((*pIoDataPointerIter)-sock);delete (*pIoDataPointerIter);*pIoDataPointerIter 0;}g_perIoDataPointerVec.clear();printf( the repeat accepting thread is exiting!\n);return 0; }bool ReleaseIOOperationData(PER_IO_OPERATION_DATA* pDataToBeDeleted) {bool retVal false;std::vectorPER_IO_OPERATION_DATA*::iterator vecIter;for(vecIter g_perIoDataPointerVec.begin(); vecIter ! g_perIoDataPointerVec.end(); vecIter){if(pDataToBeDeleted (*vecIter)){g_perIoDataPointerVec.erase(vecIter);closesocket(pDataToBeDeleted-sock);delete pDataToBeDeleted;pDataToBeDeleted 0;retVal true;break;}}return retVal; }DWORD WINAPI CompletionPortWorkerThread(LPVOID lpParameter) {CompletionPortWorkerThreadParam* pParam (CompletionPortWorkerThreadParam*)lpParameter;bool* pStillRun pParam-pBRunning;HANDLE hCompletionPort pParam-hCompletionPort;DWORD dwBytesTransfered;PER_IO_OPERATION_DATA* pIoData;WSAOVERLAPPED* pOverlap;while(true *pStillRun){dwBytesTransfered 0;pIoData 0;pOverlap 0;BOOL bGetStatus GetQueuedCompletionStatus(hCompletionPort,dwBytesTransfered,(PULONG_PTR)pIoData,pOverlap,500);if(FALSE bGetStatus){if(0 pOverlap) //did not get a packet from the queue.{continue; }else{//get a packet for a failed I/O operation.}}if(OPERATION_SEND pIoData-operationType){if(0 dwBytesTransfered) //a packet for a failed I/O operation.{printf(the client %d has close the socket!\n,pIoData-sock);ReleaseIOOperationData(pIoData);}else{// receive operation.pIoData-operationType OPERATION_RECV;pIoData-wsaBuf.buf pIoData-message;pIoData-wsaBuf.len MESSAGE_BUF_SIZE;pIoData-flags 0;ZeroMemory(pIoData-overlap,sizeof(pIoData-overlap));int recvRes WSARecv(pIoData-sock,pIoData-wsaBuf,1,pIoData-bytesRecv,pIoData-flags,pIoData-overlap,0);if(0 ! recvRes WSA_IO_PENDING ! WSAGetLastError()){printf(recv error, may be the client %d has close the socket!\n,pIoData-sock);ReleaseIOOperationData(pIoData);}}}else if(OPERATION_RECV pIoData-operationType){if(0 dwBytesTransfered) //a packet for a failed I/O operation.{printf(the client %d has close the socket!\n,pIoData-sock);ReleaseIOOperationData(pIoData);}else{// show the data receivedpIoData-message[dwBytesTransfered] \0;printf(the client %d:%s \n,pIoData-sock,pIoData-message);//send back the data received add a server: in the frontchar tempBuf[MESSAGE_BUF_SIZE];sprintf(tempBuf,server:%s,pIoData-message);strcpy(pIoData-message,tempBuf);pIoData-operationType OPERATION_SEND;pIoData-wsaBuf.buf pIoData-message;pIoData-wsaBuf.len strlen(pIoData-message);int sendRes WSASend(pIoData-sock,pIoData-wsaBuf,1,pIoData-bytesRecv,0,0,0);if(0 sendRes){pIoData-operationType OPERATION_RECV;pIoData-wsaBuf.buf pIoData-message;pIoData-wsaBuf.len MESSAGE_BUF_SIZE;pIoData-flags 0;ZeroMemory(pIoData-overlap,sizeof(pIoData-overlap));int recvRes WSARecv(pIoData-sock,pIoData-wsaBuf,1,pIoData-bytesRecv,pIoData-flags,pIoData-overlap,0);if(0 ! recvRes WSA_IO_PENDING ! WSAGetLastError()){printf(recv error, may be the client %d has close the socket!\n,pIoData-sock);ReleaseIOOperationData(pIoData);}}else if(SOCKET_ERROR sendRes WSA_IO_PENDING WSAGetLastError()){}else{printf(send error, maybe the client %d has close the socket!\n,pIoData-sock);ReleaseIOOperationData(pIoData);}}}}printf(a completion port thread is exiting!\n);return 0; } posted on 2014-12-16 08:17 NET未来之路 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/lonelyxmas/p/4166277.html
http://www.zqtcl.cn/news/715428/

相关文章:

  • 国外网站404错误页网站地址搜索
  • 做 暧视频在线观看网站北京安卓app开发公司
  • h5哪个网站可以做惠州+企业网站建设
  • 网站运营知识哪个网站可以做免费商业推广
  • 电脑做网站怎么解析域名河南郑州静默管理
  • 项目网站制作冯提莫斗鱼前在哪个网站做直播
  • 网站建设 思路wordpress 访问记录插件
  • 网站建设diyseo课程培训班费用
  • 舞蹈培训东莞网站建设做直播网站
  • app建设网站公司网站制作预算
  • 移动端网站如何开发市辖区郑州网站建设
  • 山东省双体系建设网站wordpress 帮助 主题
  • 手机怎么做三个视频网站网站建设协议一百互联
  • 创建一个网站一般步骤有哪些安徽软件定制开发
  • 网站建设平台协议书模板下载佳木斯建网站的
  • 部队网站建设招标二级域名注册平台
  • 做网站怎么调用栏目织梦搞笑图片网站源码
  • 开个小网站要怎么做南宁seo外包服务商
  • 济宁做网站的企业app网站开发学习
  • 哪个网站可以做危险化学品供求html静态网站作品
  • 豪圣建设项目管理网站创建网站的视频
  • 网站做接口自己做的网站只能用谷歌浏览器打开
  • 建设网站具体步骤python 做 网站
  • 网站源代码怎么上传wordpress标题字体大小
  • 营销型网站哪家好网页设计一张多少钱
  • 怎么搭建购物网站山东德州网站建设
  • 网站 404 错误页面是否自动跳转太原网站建设王道下拉惠
  • 美仑-专门做服装的网站淘宝详情页制作
  • 网站商城制作策划公司组织结构图
  • 商务网站建设教程企网