网站前端设计软件,沈阳正规的男科医院,重庆微信网站制作,绍兴网站设计公司说明
实现了一个回显一行字符串的服务器#xff1a;客户端发送一行字符串#xff0c;一’\n’结尾#xff0c;服务器接受完一行后就原封不动地发回给客户端。 windows下对select的能监控的Socket数量是有限制的#xff0c;若超过#xff0c;一种方案是再开一个线程。
#i…说明
实现了一个回显一行字符串的服务器客户端发送一行字符串一’\n’结尾服务器接受完一行后就原封不动地发回给客户端。 windows下对select的能监控的Socket数量是有限制的若超过一种方案是再开一个线程。
#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif /* FD_SETSIZE */代码
#include iostream
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include WinSock2.h
#include vector
#include memory#pragma comment(lib, Ws2_32.lib)struct ClientSocketItem
{ClientSocketItem(){hSocket NULL;memset(szRecv, 0, sizeof(szRecv));nRecvSize 0;bNeedWrite false;nWriteOffset 0;}SOCKET hSocket;char szRecv[1024];unsigned int nRecvSize;std::string strIp;bool bNeedWrite;//接受完成可以发送unsigned int nWriteOffset 0;
};std::vectorstd::shared_ptrClientSocketItem g_Clients;void do_accept(SOCKET hListenSocket)
{sockaddr_in mPeerAddr { 0 };int nAddrLen sizeof(sockaddr);SOCKET hClientSocket accept(hListenSocket, (sockaddr*)(mPeerAddr), nAddrLen);if (INVALID_SOCKET hClientSocket){std::cout accept failed with error WSAGetLastError() std::endl;}else{unsigned long nNoBlock 0;ioctlsocket(hClientSocket, FIONBIO, nNoBlock);std::string strIpAddr inet_ntoa(mPeerAddr.sin_addr);std::cout accept success, peer ip is strIpAddr.c_str() std::endl;auto pClient std::make_sharedClientSocketItem();pClient-hSocket hClientSocket;pClient-strIp strIpAddr;g_Clients.push_back(pClient);}
}bool do_read(const std::shared_ptrClientSocketItem pClient )
{if (!pClient){return false;}char c 0; //测试用每次只读一个字符int nRecvValue recv(pClient-hSocket, c, 1, 0);if (nRecvValue 0){pClient-szRecv[pClient-nRecvSize] c;pClient-nRecvSize 1;std::cout read one char: c std::endl;if (c \n){std::cout read finished std::endl;pClient-bNeedWrite true;}return true;}else if (0 nRecvValue){std::cout peer client closed std::endl;closesocket(pClient-hSocket);return false;}else{int nError WSAGetLastError();if (WSAEWOULDBLOCK ! nError){std::cerr recv failed with error nError std::endl;closesocket(pClient-hSocket);return false;}std::cout next recv std::endl;return true;}
}bool do_write(const std::shared_ptrClientSocketItem pClient)
{if (!pClient){return false;}if (!pClient-bNeedWrite){return true;}//测试用每次只发送一个字符int nRet send(pClient-hSocket, pClient-szRecv pClient-nWriteOffset, 1, 0);if (nRet 0){std::cout send one char: pClient-szRecv[pClient-nWriteOffset] std::endl;pClient-nWriteOffset 1;if (pClient-nWriteOffset pClient-nRecvSize){std::cout send finished, close client( pClient-strIp.c_str() ) std::endl;pClient-bNeedWrite false;closesocket(pClient-hSocket);return false;}return true;}else{int nError WSAGetLastError();if (WSAEWOULDBLOCK ! nError){std::cerr send failed with error nError std::endl;closesocket(pClient-hSocket);return false;}std::cout next send std::endl;return true;}
}int main(int argc, char* argv)
{WORD wVersionRequested MAKEWORD(2, 2);WSADATA wsaData { 0 };int err WSAStartup(wVersionRequested, wsaData);if (err ! 0){return -1;}if (LOBYTE(wsaData.wVersion) ! 2 ||HIBYTE(wsaData.wVersion) ! 2){WSACleanup();return -1;}SOCKET hListenSocket socket(AF_INET, SOCK_STREAM, 0);if (INVALID_SOCKET hListenSocket){std::cerr create socket failed with error WSAGetLastError() std::endl;return -1;}sockaddr_in mSockAddrIn { 0 };mSockAddrIn.sin_family AF_INET;mSockAddrIn.sin_port htons((u_short)8878);mSockAddrIn.sin_addr.S_un.S_addr inet_addr(0.0.0.0);if (SOCKET_ERROR bind(hListenSocket, (sockaddr*)(mSockAddrIn),sizeof(sockaddr))){std::cerr bind failed with error WSAGetLastError() std::endl;return -1;}if (SOCKET_ERROR listen(hListenSocket, SOMAXCONN)){std::cerr listen failed with error WSAGetLastError() std::endl;return -1;}std::vectorSOCKET mAllClients;while (true){fd_set readfds;fd_set writefds;fd_set exceptfds;FD_ZERO(readfds);FD_ZERO(writefds);FD_ZERO(exceptfds);FD_SET(hListenSocket, readfds);//FD_SET(hListenSocket, writefds);//FD_SET(hListenSocket, exceptfds);for (auto it g_Clients.begin(); it ! g_Clients.end(); it){std::shared_ptrClientSocketItem pClientItem *it;if (!pClientItem) continue;FD_SET(pClientItem-hSocket, readfds);if (pClientItem-bNeedWrite)//否则select会一直有事件{FD_SET(pClientItem-hSocket, writefds);}FD_SET(pClientItem-hSocket, exceptfds);}int nRet select(0, readfds, writefds, exceptfds, nullptr);std::cout select return with nRet std::endl;if (nRet 0){//readif (FD_ISSET(hListenSocket, readfds)){do_accept(hListenSocket);}for (auto it g_Clients.begin(); it ! g_Clients.end();){std::shared_ptrClientSocketItem pClientItem *it;if (pClientItem FD_ISSET(pClientItem-hSocket, readfds)){if (!do_read(pClientItem)){it g_Clients.erase(it);continue;}}it;}//writefor (auto it g_Clients.begin(); it ! g_Clients.end();){std::shared_ptrClientSocketItem pClientItem *it;if (pClientItem FD_ISSET(pClientItem-hSocket, writefds)){if (!do_write(pClientItem)){it g_Clients.erase(it);continue;}}it;}//end of for//error for (auto it g_Clients.begin(); it ! g_Clients.end();){std::shared_ptrClientSocketItem pClientItem *it;if (pClientItem FD_ISSET(pClientItem-hSocket, exceptfds)){std::cerr client socket except, close and remove it std::endl;closesocket(pClientItem-hSocket);it g_Clients.erase(it);continue;}it;}//end of for}else{std::cerr select failed with error WSAGetLastError() std::endl;}}return 0;
}