Windows Socket 编程:支持多线程(TCP)(环境:VS2010)几点说明:
(1)发送的数据不能有空格;
(2)这是控制台应用程序;
1、UserMesInfo.h 公共文件,客户端和服务器端公用;
1 #ifndef User_Mes_Sock
2#define User_Mes_Sock
3 #include
4#endif
5
6const short MesLogin = 1001;
7const short MesError = 1002;
8const short MesNormal = 1003;
9const short LoginSuc = 1004;
10const short MesToAll = 1005;
11const short OnLineUser = 1010;
12
13
14//User Struct
15struct UserInfo
16 {
17short userId;
18char userName[32];
19 SOCKET userSock;
20 LONG userAddr;
21 UserInfo *pNext;
22 };
23
24//Message Struct
25struct MesInfo
26 {
27short MesType;
28char fromUserName[32]; 29char toUserName[32]; 30char MesContent[1024];
31 };
2、TCP:客户端程序
1 #include
2 #include
3 #include
4
5 #include "UserMesInfo.h"
6
7#pragma comment(lib,"ws2_32.lib")
8
9using namespace std;
10
11 BOOL isLogin = false;
12
13
14string charToString(char temp[])
15 {
16string tempStr = "";
17for(int i = 0; i < sizeof(temp); i++) 18 tempStr += temp[i];
19return tempStr;
20 }
21
22 BOOL SendMes(SOCKET servSocket)
23 {
24 SOCKET servSock = servSocket;
25while(TRUE)
26 {
27int tempWho;
28char sendBuff[1024] = {0};
29if(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 }
35if( isLogin && tempWho == 1)
36 {
37//To One
38 printf("Please input NAME you want to CHAT : ");
39char 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 : ");
44char 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 : ");
51char 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){
59char getOnLineUsers[4];
60 memcpy(getOnLineUsers, &OnLineUser, 2);
61 send(servSock, getOnLineUsers, sizeof(getOnLineUsers), 0);
62 } else if(isLogin && tempWho == 4){
63break;
64 } else if(isLogin){
65 printf("You input Error! Please Again !");
66 }
67
68 }
69return 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
80char recvBuf[1024] = {0};
81
82while(true)
83 {
84 memset(recvBuf, 0x00, 1024);
85int recvLen = recv(cliSocket, recvBuf, 1024, 0); 86if(recvLen > 0)
87 {
88short megId = *(short*)recvBuf;
89switch(megId)
90 {
92 {
93//char userName[32] = {0};
94//memcpy(userName, recvBuf+2, 4);
95 printf("Login Success !\n");
96 isLogin = true;
97 }
98break;
99case MesNormal:
100 {
101char Mess[1000];
102 memcpy(Mess, recvBuf+2, sizeof(recvBuf)-2); 103 printf("==> Me :%s\n", Mess);
104
105 }
106break;
107case MesToAll:
108 {
109char Mess[1000];
110 memcpy(Mess, recvBuf+2, sizeof(recvBuf)-2); 111 printf("==> All :%s\n", Mess);
112 }
113break;
115 {
116char onLineUser[100] = {0};
117
118memcpy(onLineUser, recvBuf+2, sizeof(recvBuf)-2);
119
120//string userStr = charToString(onLineUser); 121
122for(int i =0; i < sizeof(onLineUser); i++)
123 cout< 124 125//printf("%s\n", userStr); 126 cout< 127 printf("\n"); 128 129 } 130break; 131default : 132break; 133 } 134 }//end if 135 }//end while 136 137return0; 138 } 139 140int main() 141 { 142 WORD wVersionRequested; 143 WSADATA wsaData; 144int err; 145 146 wVersionRequested = MAKEWORD(2, 2); 147 148 err = WSAStartup(wVersionRequested, &wsaData); 149if (err != 0) { 150 printf("WSAStartup failed with error: %d\n", err); 151return1; 152 } 153 154if(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(); 159return1; 160 } 161else 162 printf("The Winsock 2.2 dll was found okay\n"); 163 164 165 SOCKET clientSock = socket(AF_INET, SOCK_STREAM, 0); 166 167if(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 179int ret = connect(clientSock, (sockaddr*)&addrClient, sizeof(SOCKADDR)); 180if (ret) 181 { 182 printf("连接失败\n"); 183return -1; 184 } 185 186HANDLE thHandle = CreateThread(NULL, 0, ProcThread, &clientSock, 0, NULL); 187 188if(NULL == thHandle) 189 { 190 cout<<"Create Thread failed !"< 191return -1; 192 } 193 194char 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 205char 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); 211int 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"); 222return0; 223 } 3、TCP:服务器端程序 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include "UserMesInfo.h" 7 8#pragma comment(lib,"ws2_32.lib") 9 10using namespace std; 11 12 UserInfo *gUserInfo ; 13 14string charToString(char temp[]) 15 { 16string tempStr = ""; 17for(int i = 0; i < sizeof(temp); i++) 18 tempStr += temp[i]; 19return tempStr; 20 } 21 22 23 DWORD WINAPI ProcMes(LPVOID lpParameter) 24 { 25 SOCKET cliSocket = ((UserInfo*)lpParameter)->userSock; 26//SOCKADDR_IN sockFrom ; 27 28char recvBuf[1024]; 29//int length = sizeof(SOCKADDR); 30 31while(true) 32 { 33 memset(recvBuf, 0x00, 1024); 34 recv(cliSocket, recvBuf, 1024, 0); 35 36short MesType = *(short*)recvBuf; 37 38switch(MesType) 39 { 40case MesLogin: 41 { 42static short USERID = 1001; 43 UserInfo* userInfo = new UserInfo; 44char* userName = (char*)(recvBuf + 2); 45 strcpy_s(userInfo->userName, userName); 46 userInfo->userId = USERID++; 47 userInfo->userSock = cliSocket; 48userInfo->userAddr = ((UserInfo*)lpParameter)->userAddr; 49 userInfo->pNext = NULL; 50 51if(!gUserInfo) 52 { 53 gUserInfo = userInfo; 54 }else 55 { 56 userInfo->pNext = gUserInfo; 57 gUserInfo = userInfo; 58 } 59printf("Login : %s ==> %d !\n", userInfo->userName, userInfo->userId); 60 61char loginInfo[4] = {0}; 62 memcpy(loginInfo, &LoginSuc, 2); 63 64int i = send(cliSocket, loginInfo, strlen(loginInfo), 0); 65 66 } 67break; 68case MesNormal: 69 { 70//printf("The Normal Message !"); 71char toName[32] = {0}; 72 memcpy(toName, recvBuf+2, 32); 73 cout< 74char Message[1000] = {0}; 75 memcpy(Message, recvBuf+34, sizeof(recvBuf)-34); 76 printf("%s\n", Message); 77 78char 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; 86while(tempUser) 87 { 88if(!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 } 96if(!sendFlag) 97 { 98 printf("Send Failed !\n"); 99 } 100 101 } 102break; 103case MesToAll: 104 { 105char Message[1000] = {0}; 106 memcpy(Message, recvBuf+2, sizeof(recvBuf)-2); 107 UserInfo* tempUser = gUserInfo; 108char sendMes[1002]; 109 memcpy(sendMes, &MesToAll, 2); 110 memcpy(sendMes+2, Message, sizeof(Message)); 111while(tempUser) 112 { 113 SOCKET toSock = tempUser->userSock; 114int i = send(toSock, sendMes, strlen(sendMes)+1, 0); 115if(i > 0) 116 { 117 printf("Send To %s Success !\n", tempUser->userName); 118 } 119 tempUser = tempUser->pNext; 120 } 121 } 122break; 123case MesError: 124//printf("The Error Message !"); 125break; 126case OnLineUser: 127 { 128 129char onLineUserBuff[1000] = {0}; 130 UserInfo* tempUser = gUserInfo; 131 132 memcpy(onLineUserBuff, &OnLineUser, 2); 133 134int i = 0; 135string userStr = ""; 136while(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 } 144memcpy(onLineUserBuff+2, userStr.c_str(), userStr.length()); 145send(cliSocket, onLineUserBuff, sizeof(onLineUserBuff), 0); 146 147 } 148break; 149default: 150//printf("The Default Process !"); 151break; 152 } 153 154 } 155 156 157return0; 158 } 159 160int main() 161 { 162 WORD wVersionRequested; 163 WSADATA wsaData; 164int err; 165 166 wVersionRequested = MAKEWORD(2, 2); 167 168 err = WSAStartup(wVersionRequested, &wsaData); 169if (err != 0) {