#include <stdio.h> #include <winsock.h> #include <list> #include <vector> #include <map> #pragma comment(lib, "ws2_32.lib") #define SERVER_HOST "192.168.1.66" #define SERVER_PORT 6000 bool initWinsock2() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("Windows sockets 2.2 startup"); return false; } else { printf("Using %s (Status: %s)/n", wsaData.szDescription, wsaData.szSystemStatus); printf("with API versions %d.%d to %d.%d/n/n", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion), LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion)); return true; } } void finalWinsock2() { WSACleanup(); } bool setNonBlock(SOCKET sock) { unsigned long ul = 1; if (ioctlsocket(sock, FIONBIO, (unsigned long *)&ul) == SOCKET_ERROR) { printf("ioctlsocket() error/n"); return false; } return true; } // thread base class XThread { public: bool init(); protected: virtual void run() = 0; private: static DWORD WINAPI workThread(LPVOID lpParameter); }; bool XThread::init() { HANDLE m_hCThread = CreateThread(NULL, 0, workThread, this, 0, NULL); if(m_hCThread == NULL) { return false; } return true; } DWORD WINAPI XThread::workThread(LPVOID lpParameter) { XThread *ptXThread = (XThread *)lpParameter; if (ptXThread != NULL) { ptXThread->run(); } return 0; } // parser manager class ProParser : public XThread { public: bool insert(int sock, void const * buffer, int length); protected: virtual void run(); private: std::map<int, std::vector<unsigned char> > mapList; }; bool ProParser::insert(int sock, void const * buffer, int length) { if (buffer == NULL) { return false; } mapList[sock].insert(mapList[sock].end(), static_cast<unsigned char const *>(buffer), static_cast<unsigned char const *>(buffer) + length); return true; } void ProParser::run() { for ( ; ; ) { for (std::map<int, std::vector<unsigned char> >::iterator iter = mapList.begin(); iter != mapList.end(); ++iter) { printf("socket %u ", iter->first); for (int i = 0; i < iter->second.size(); i++) { printf("%c", (iter->second)[i]); } printf("/n"); } } // end for } // recv manager class RecvManager : public XThread { public: RecvManager() : pParser(NULL) {} RecvManager(ProParser *parser) : pParser(parser) {} void push(SOCKET sock) { sockList.push_back(sock); } void remove(SOCKET sock) { sockList.remove(sock); } protected: virtual void run(); private: std::list<SOCKET> sockList; ProParser *pParser; }; void RecvManager::run() { char szbuffer[2048]; int read_byte, ret, maxsock; fd_set infds; sockaddr_in client_addr; int len = sizeof(struct sockaddr_in); for ( ; ; ) { if (sockList.empty()) { Sleep(100); continue; } FD_ZERO(&infds); maxsock = 0; for (std::list<SOCKET>::iterator iter = sockList.begin(); iter != sockList.end(); ++iter) { FD_SET(*iter, &infds); if (*iter > maxsock) { maxsock = *iter; } } ret = select(maxsock + 1, &infds, NULL, NULL, NULL); if(ret == -1) // -1 error 0 time out { break; } for (std::list<SOCKET>::iterator iter = sockList.begin(); iter != sockList.end(); ) { if (!FD_ISSET(*iter, &infds)) { ++iter; continue; } // recv buffer read_byte = recv(*iter, szbuffer, sizeof(szbuffer), 0); if (read_byte <= 0) { getpeername(*iter, (struct sockaddr *)&client_addr, &len); printf("> close %s : %u/n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); closesocket(*iter); sockList.erase(iter++); } else { pParser->insert(*iter, szbuffer, read_byte); ++iter; } } } // end for ( ; ; ) } int main(int argc, char *argv[]) { initWinsock2(); ProParser parser; parser.init(); RecvManager recvmanager(&parser); recvmanager.init(); SOCKET s; struct sockaddr_in ser; char buffer[128] = "hello word"; for ( ; ; ) { s = socket(AF_INET, SOCK_STREAM, 0); ser.sin_family = AF_INET; ser.sin_addr.s_addr = inet_addr(SERVER_HOST); ser.sin_port = htons(SERVER_PORT); if(connect(s, (struct sockaddr *)&ser, sizeof(struct sockaddr)) < 0) { printf("connect error/n"); continue; } setNonBlock(s); send(s, buffer, sizeof(buffer), 0); // add socket to recv manager recvmanager.push(s); } for ( ; ; ) { Sleep(10); } finalWinsock2(); return 0; }