Windows Socket 编程 : 支持多线程(TCP)(环境:VS2010)
几点说明:
(1)发送的数据不能有空格;
(2)这是控制台应用程序;
1、UserMesInfo.h 公共文件,客户端和服务器端公用;
1 #ifndef User_Mes_Sock 2 #define User_Mes_Sock 3 #include <winsock2.h> 4 #endif 5 6 const short MesLogin = 1001; 7 const short MesError = 1002; 8 const short MesNormal = 1003; 9 const short LoginSuc = 1004; 10 const short MesToAll = 1005; 11 const short OnLineUser = 1010; 12 13 14 //User Struct 15 struct UserInfo 16 { 17 short userId; 18 char userName[32]; 19 SOCKET userSock; 20 LONG userAddr; 21 UserInfo *pNext; 22 }; 23 24 //Message Struct 25 struct MesInfo 26 { 27 short MesType; 28 char fromUserName[32]; 29 char toUserName[32]; 30 char MesContent[1024]; 31 };
2、TCP:客户端程序
1 #include <iostream> 2 #include <stdlib.h> 3 #include <WinSock2.h> 4 5 #include "UserMesInfo.h" 6 7 #pragma comment(lib,"ws2_32.lib") 8 9 using namespace std; 10 11 BOOL isLogin = false; 12 13 14 string charToString(char temp[]) 15 { 16 string tempStr = ""; 17 for(int i = 0; i < sizeof(temp); i++) 18 tempStr += temp[i]; 19 return tempStr; 20 } 21 22 BOOL SendMes(SOCKET servSocket) 23 { 24 SOCKET servSock = servSocket; 25 while(TRUE) 26 { 27 int tempWho; 28 char sendBuff[1024] = {0}; 29 if(isLogin) 30 { 31 printf(" '1' : speak to ONE ;\n '2' : speak to ALL ;\n '3' : OnLine Users ; \n '4' : Exit ;\n"); 32 33 cin>>tempWho; 34 } 35 if( isLogin && tempWho == 1) 36 { 37 //To One 38 printf("Please input NAME you want to CHAT : "); 39 char toName[32] = {0}; 40 scanf("%s", toName); 41 memcpy(sendBuff, &MesNormal, 2); 42 memcpy(sendBuff+2, toName, 32); 43 printf("Please input what do you want to say : "); 44 char Message[1000] = {0}; 45 scanf("%s", Message); 46 memcpy(sendBuff+34, Message, strlen(Message)); 47 send(servSock, sendBuff, sizeof(sendBuff)+1, 0); 48 } else if(isLogin && tempWho == 2){ 49 //To ALL 50 printf("Please input DATA : "); 51 char Message[1000] = {0}; 52 scanf("%s", Message); 53 54 memcpy(sendBuff, &MesToAll, 2); 55 memcpy(sendBuff+2, Message, strlen(Message)); 56 send(servSock, sendBuff, sizeof(sendBuff)+1, 0); 57 58 } else if(isLogin && tempWho == 3){ 59 char getOnLineUsers[4]; 60 memcpy(getOnLineUsers, &OnLineUser, 2); 61 send(servSock, getOnLineUsers, sizeof(getOnLineUsers), 0); 62 } else if(isLogin && tempWho == 4){ 63 break; 64 } else if(isLogin){ 65 printf("You input Error! Please Again !"); 66 } 67 68 } 69 return TRUE; 70 } 71 72 73 DWORD WINAPI ProcThread(LPVOID lpParameter) 74 { 75 SOCKET cliSocket = *(SOCKET*)lpParameter; 76 77 //SOCKADDR_IN sockFrom ; 78 //int length = sizeof(SOCKADDR); 79 80 char recvBuf[1024] = {0}; 81 82 while(true) 83 { 84 memset(recvBuf, 0x00, 1024); 85 int recvLen = recv(cliSocket, recvBuf, 1024, 0); 86 if(recvLen > 0) 87 { 88 short megId = *(short*)recvBuf; 89 switch(megId) 90 { 91 case LoginSuc: 92 { 93 //char userName[32] = {0}; 94 //memcpy(userName, recvBuf+2, 4); 95 printf("Login Success !\n"); 96 isLogin = true; 97 } 98 break; 99 case MesNormal: 100 { 101 char Mess[1000]; 102 memcpy(Mess, recvBuf+2, sizeof(recvBuf)-2); 103 printf(" ==> Me :%s\n", Mess); 104 105 } 106 break; 107 case MesToAll: 108 { 109 char Mess[1000]; 110 memcpy(Mess, recvBuf+2, sizeof(recvBuf)-2); 111 printf(" ==> All :%s\n", Mess); 112 } 113 break; 114 case OnLineUser: 115 { 116 char onLineUser[100] = {0}; 117 118 memcpy(onLineUser, recvBuf+2, sizeof(recvBuf)-2); 119 120 //string userStr = charToString(onLineUser); 121 122 for(int i =0; i < sizeof(onLineUser); i++) 123 cout<<onLineUser[i]; 124 125 //printf("%s\n", userStr); 126 cout<<endl<<onLineUser<<endl; 127 printf("\n"); 128 129 } 130 break; 131 default : 132 break; 133 } 134 }//end if 135 }// end while 136 137 return 0; 138 } 139 140 int main() 141 { 142 WORD wVersionRequested; 143 WSADATA wsaData; 144 int err; 145 146 wVersionRequested = MAKEWORD(2, 2); 147 148 err = WSAStartup(wVersionRequested, &wsaData); 149 if (err != 0) { 150 printf("WSAStartup failed with error: %d\n", err); 151 return 1; 152 } 153 154 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { 155 /* Tell the user that we could not find a usable */ 156 /* WinSock DLL. */ 157 printf("Could not find a usable version of Winsock.dll\n"); 158 WSACleanup(); 159 return 1; 160 } 161 else 162 printf("The Winsock 2.2 dll was found okay\n"); 163 164 165 SOCKET clientSock = socket(AF_INET, SOCK_STREAM, 0); 166 167 if(clientSock == -1) 168 { 169 perror("socket创建出错!"); 170 exit(1); 171 } 172 173 SOCKADDR_IN addrClient; 174 addrClient.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 175 addrClient.sin_family = AF_INET; 176 addrClient.sin_port = htons(6000); 177 178 179 int ret = connect(clientSock, (sockaddr*)&addrClient, sizeof(SOCKADDR)); 180 if (ret) 181 { 182 printf("连接失败\n"); 183 return -1; 184 } 185 186 HANDLE thHandle = CreateThread(NULL, 0, ProcThread, &clientSock, 0, NULL); 187 188 if(NULL == thHandle) 189 { 190 cout<<"Create Thread failed !"<<endl; 191 return -1; 192 } 193 194 char userName[32]; 195 printf("Please input name : "); 196 scanf_s("%s", userName, 31); 197 198 /* 199 UserInfo* user = new UserInfo; 200 user->userSock = clientSock; 201 strcpy_s(user->userName, userName); 202 user->userAddr = addrClient.sin_addr.S_un.S_addr; 203 */ 204 205 char loginInfo[64] = {0}; 206 memcpy(loginInfo, &MesLogin, 2); 207 memcpy(loginInfo+2, userName, strlen(userName)); 208 209 210 //int a = send(clientSock, loginInfo, strlen(loginInfo), 0); 211 int a = send(clientSock, loginInfo, strlen(loginInfo), 0); 212 213 SendMes(clientSock); 214 215 //Sleep(20000); 216 //closesocket(clientSock); 217 CloseHandle(thHandle); 218 WSACleanup(); 219 220 221 system("PAUSE"); 222 return 0; 223 }
3、TCP:服务器端程序
1 #include <iostream> 2 #include <cstdlib> 3 #include <winsock2.h> 4 #include <string> 5 #include <Windows.h> 6 #include "UserMesInfo.h" 7 8 #pragma comment(lib,"ws2_32.lib") 9 10 using namespace std; 11 12 UserInfo *gUserInfo ; 13 14 string charToString(char temp[]) 15 { 16 string tempStr = ""; 17 for(int i = 0; i < sizeof(temp); i++) 18 tempStr += temp[i]; 19 return tempStr; 20 } 21 22 23 DWORD WINAPI ProcMes(LPVOID lpParameter) 24 { 25 SOCKET cliSocket = ((UserInfo*)lpParameter)->userSock; 26 //SOCKADDR_IN sockFrom ; 27 28 char recvBuf[1024]; 29 //int length = sizeof(SOCKADDR); 30 31 while(true) 32 { 33 memset(recvBuf, 0x00, 1024); 34 recv(cliSocket, recvBuf, 1024, 0); 35 36 short MesType = *(short*)recvBuf; 37 38 switch(MesType) 39 { 40 case MesLogin: 41 { 42 static short USERID = 1001; 43 UserInfo* userInfo = new UserInfo; 44 char* userName = (char*)(recvBuf + 2); 45 strcpy_s(userInfo->userName, userName); 46 userInfo->userId = USERID++; 47 userInfo->userSock = cliSocket; 48 userInfo->userAddr = ((UserInfo*)lpParameter)->userAddr; 49 userInfo->pNext = NULL; 50 51 if(!gUserInfo) 52 { 53 gUserInfo = userInfo; 54 }else 55 { 56 userInfo->pNext = gUserInfo; 57 gUserInfo = userInfo; 58 } 59 printf("Login : %s ==> %d !\n", userInfo->userName, userInfo->userId); 60 61 char loginInfo[4] = {0}; 62 memcpy(loginInfo, &LoginSuc, 2); 63 64 int i = send(cliSocket, loginInfo, strlen(loginInfo), 0); 65 66 } 67 break; 68 case MesNormal: 69 { 70 //printf("The Normal Message !"); 71 char toName[32] = {0}; 72 memcpy(toName, recvBuf+2, 32); 73 cout<<toName<<endl; 74 char Message[1000] = {0}; 75 memcpy(Message, recvBuf+34, sizeof(recvBuf)-34); 76 printf("%s\n", Message); 77 78 char sendMes[1006]; 79 memcpy(sendMes, &MesNormal, 2); 80 memcpy(sendMes+2, recvBuf+34, sizeof(recvBuf)-34); 81 82 //send(toSock, sendMes, sizeof(sendMes), 0); 83 84 UserInfo* tempUser = gUserInfo; 85 BOOL sendFlag = false; 86 while(tempUser) 87 { 88 if(!memcmp(toName, tempUser->userName, strlen(toName))) 89 { 90 SOCKET toSock = tempUser->userSock; 91 send(toSock, sendMes, strlen(sendMes)+1, 0); 92 sendFlag = true; 93 } 94 tempUser = tempUser->pNext; 95 } 96 if(!sendFlag) 97 { 98 printf("Send Failed !\n"); 99 } 100 101 } 102 break; 103 case MesToAll: 104 { 105 char Message[1000] = {0}; 106 memcpy(Message, recvBuf+2, sizeof(recvBuf)-2); 107 UserInfo* tempUser = gUserInfo; 108 char sendMes[1002]; 109 memcpy(sendMes, &MesToAll, 2); 110 memcpy(sendMes+2, Message, sizeof(Message)); 111 while(tempUser) 112 { 113 SOCKET toSock = tempUser->userSock; 114 int i = send(toSock, sendMes, strlen(sendMes)+1, 0); 115 if(i > 0) 116 { 117 printf("Send To %s Success !\n", tempUser->userName); 118 } 119 tempUser = tempUser->pNext; 120 } 121 } 122 break; 123 case MesError: 124 //printf("The Error Message !"); 125 break; 126 case OnLineUser: 127 { 128 129 char onLineUserBuff[1000] = {0}; 130 UserInfo* tempUser = gUserInfo; 131 132 memcpy(onLineUserBuff, &OnLineUser, 2); 133 134 int i = 0; 135 string userStr = ""; 136 while(tempUser) 137 { 138 userStr += charToString(tempUser->userName); 139 //处理方式有问题 140 //memcpy(onLineUserBuff+2, tempUser->userName, 32); 141 //send(cliSocket, onLineUserBuff, sizeof(onLineUserBuff), 0); 142 tempUser = tempUser->pNext; 143 } 144 memcpy(onLineUserBuff+2, userStr.c_str(), userStr.length()); 145 send(cliSocket, onLineUserBuff, sizeof(onLineUserBuff), 0); 146 147 } 148 break; 149 default: 150 //printf("The Default Process !"); 151 break; 152 } 153 154 } 155 156 157 return 0; 158 } 159 160 int main() 161 { 162 WORD wVersionRequested; 163 WSADATA wsaData; 164 int err; 165 166 wVersionRequested = MAKEWORD(2, 2); 167 168 err = WSAStartup(wVersionRequested, &wsaData); 169 if (err != 0) { 170 printf("WSAStartup failed with error: %d\n", err); 171 return 1; 172 } 173 174 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { 175 /* Tell the user that we could not find a usable */ 176 /* WinSock DLL. */ 177 printf("Could not find a usable version of Winsock.dll\n"); 178 WSACleanup(); 179 return 1; 180 } 181 else 182 printf("The Winsock 2.2 dll was found okay\n"); 183 184 185 SOCKET servSock = socket(AF_INET, SOCK_STREAM, 0); 186 187 SOCKADDR_IN addrServ ; 188 addrServ.sin_family = AF_INET; 189 addrServ.sin_port = htons(6000); 190 addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY); 191 192 bind(servSock, (SOCKADDR*)&addrServ, sizeof(SOCKADDR)); 193 194 if(listen(servSock, 20) == SOCKET_ERROR) 195 { 196 printf("listen failed with error: %ld\n", WSAGetLastError()); 197 closesocket(servSock); 198 WSACleanup(); 199 return -1; 200 } 201 202 203 while(true) 204 { 205 //wait for users Login, and create thread for it 206 SOCKADDR_IN cliAddr; 207 int length = sizeof(SOCKADDR); 208 209 SOCKET cliSock = accept(servSock, (SOCKADDR*)&cliAddr, &length); 210 211 if(INVALID_SOCKET == cliSock) 212 { 213 printf("listen failed with error: %ld\n", WSAGetLastError()); 214 closesocket(cliSock); 215 WSACleanup(); 216 return -1; 217 } 218 219 UserInfo* user = new UserInfo; 220 221 user->userSock = cliSock; 222 user->userAddr = cliAddr.sin_addr.S_un.S_addr; 223 224 //cout<<sizeof(user->userName)<<endl; 225 226 HANDLE loginHandle = CreateThread(NULL, 0, ProcMes, (LPVOID)user, 0, NULL); 227 228 if(NULL == loginHandle) 229 { 230 cout<<"Create Thread failed !"<<endl; 231 return -1; 232 } 233 CloseHandle(loginHandle); 234 235 } 236 //Sleep(20000); 237 closesocket(servSock); 238 WSACleanup(); 239 240 system("PAUSE"); 241 return 0; 242 }