转自:http://blog.csdn.net/neicole/article/details/7539444 并加以改进
Server程序:
1 // OneServerMain.cpp 2 3 #include <iostream> 4 #include <cstdio> 5 #include <string> 6 #include <cstring> 7 #include <vector> 8 #include <iterator> 9 #include <algorithm> 10 #include <Winsock2.h> 11 #include <Windows.h> 12 13 using namespace std; 14 HANDLE bufferMutex; // 令其能互斥成功正常通信的信号量句柄 15 SOCKET sockConn; // 客户端的套接字 16 vector <SOCKET> clientSocketGroup; 17 18 DWORD WINAPI SendMessageThread(LPVOID IpParameter); 19 DWORD WINAPI ReceiveMessageThread(LPVOID IpParameter); 20 21 int main() 22 { 23 // 加载socket动态链接库(dll) 24 WORD wVersionRequested; 25 WSADATA wsaData; // 该结构用于接收Wjndows Socket的结构信息 26 wVersionRequested = MAKEWORD( 2, 2 ); // 请求2.2版本的WinSock库 27 int err = WSAStartup( wVersionRequested, &wsaData ); 28 if ( err != 0 ) 29 { 30 return -1; // 返回值为零的时候是表示成功申请WSAStartup 31 } 32 if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) // 检测是否2.2版本的socket库 33 { 34 WSACleanup( ); 35 return -1; 36 } 37 38 // 创建socket操作,建立流式套接字,返回套接字号sockSrv 39 SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); 40 41 // 套接字sockSrv与本地地址相连 42 SOCKADDR_IN addrSrv; 43 addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 将INADDR_ANY转换为网络字节序,调用 htonl(long型)或htons(整型) 44 addrSrv.sin_family = AF_INET; 45 addrSrv.sin_port = htons(6000); 46 47 // 绑定套接字 48 if(SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR))) 49 { 50 return -1; 51 } 52 53 // 将套接字设置为监听模式(连接请求),listen()通知TCP服务器准备好接收连接,最大连接数为20 54 listen(sockSrv, 20); 55 56 cout << "服务器已成功就绪,若服务器想发送信息给客户端,可直接输入内容后按回车. "; 57 58 // 设置信号量的值 59 bufferMutex = CreateSemaphore(NULL, 1, 1, NULL); 60 61 // 建立一个向所有客户端发送信息的线程 62 HANDLE sendThread = CreateThread(NULL, 0, SendMessageThread, NULL, 0, NULL); 63 64 while(true)// 不断等待客户端请求的到来 65 { 66 sockConn = accept(sockSrv, NULL, NULL); 67 if (SOCKET_ERROR != sockConn) 68 { 69 clientSocketGroup.push_back(sockConn); //若连接成功则将客户端套接字加入clientSocketGroup 70 } 71 72 // 建立一个接收指定客户端信息的线程 73 HANDLE receiveThread = CreateThread(NULL, 0, ReceiveMessageThread, (LPVOID)sockConn, 0, NULL); 74 75 WaitForSingleObject(bufferMutex, INFINITE); // P操作(资源未被占用则使用资源) 76 if(NULL == receiveThread) 77 { 78 cout << "CreatThread AnswerThread() failed." << endl; 79 } 80 else 81 { 82 cout << "Create Receive Client Thread OK." << endl; 83 } 84 ReleaseSemaphore(bufferMutex, 1, NULL); // V操作(资源占用完毕将其释放) 85 } 86 87 WaitForSingleObject(sendThread, INFINITE); // 等待线程结束 88 CloseHandle(sendThread); 89 CloseHandle(bufferMutex); 90 WSACleanup(); // 终止对套接字库的使用 91 system("pause"); 92 return 0; 93 } 94 95 96 DWORD WINAPI SendMessageThread(LPVOID IpParameter) 97 { 98 while(1) 99 { 100 string talk; 101 getline(cin, talk); 102 WaitForSingleObject(bufferMutex, INFINITE); // P(资源未被占用) 103 104 //若服务器要主动关闭 105 if("quit" == talk) 106 { 107 talk.push_back('