赞
踩
服务端
1、负责转发双方的消息
|----1.1、接收客户端A的消息,并转发给客户端B
|----1.2、接收客户端B的消息,并转发给客户端A
客户端
1、可以发送消息给对方
2、可以接受对方的消息
关于线程
1、服务的与客户端均使用了线程,在客户端中主线程负责我方发送消息,另一个线程(函数名:ThreadReceive)用于接收对方的消息并显示在控制台(底部给出参考链接)。
工作流程图
详细流程
1、因为是两个客户端聊天,所以在服务端需要得到两个客户端的Socket。服务端首先等待第一个客户端连接,第一个客户端连接成功后,再等待第二个客户端连接,双方都连接后,服务端开始工作(上图绿色字体)。
2、客户端会有一个单独的线程来接收来自服务器的消息(其实接收的是对方的消息,由服务端转发)
注:服务的作用是负责转发两个客户端之间的消息,让双方都能收到对方的消息。所以服务端是等待两次Socket连接,第一次是第一个客户端,第二次是第二个客户端,在只有一个客户端连接的情况下,发消息并没有意义。
运行效果图
客户端代码(Client[32bit]V1.4.cpp)
#include <WinSock2.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <process.h> #include <windows.h> #pragma comment(lib,"ws2_32.lib") /* * * * * * * * * * * * * * * * Client * * * * * * * * * *夏雨程_YKC *alanlw21@qq.com * *Dev-C++5.11编译报错附加:-lwsock32 * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void ThreadReceive(PVOID param); void SendReceiveException(int e); SOCKET ClientSocket = INVALID_SOCKET; char name[18] = ""; int main(void) { system("title Client V1.4"); system("mode con cols=60 lines=23"); system("color 9F"); SOCKADDR_IN ServerAddr = { 0 }; WSADATA wsaData = { 0 }; USHORT uPort = 47168;//服务端端口 if (WSAStartup(MAKEWORD(2, 2), &wsaData)) { printf("WSAStartup failed with error code: %d\n", WSAGetLastError());system("pause"); return -1; } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { printf("wVersion was not 2.2\n");system("pause"); return -1; } ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ClientSocket == INVALID_SOCKET) { printf("socket failed with error code: %d\n", WSAGetLastError());system("pause"); return -1; } //服务器地址:127.0.0.1 char IP[20] = "127.0.0.1"; printf("请输入你的昵称:"); gets(name); ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(uPort); ServerAddr.sin_addr.S_un.S_addr = inet_addr(IP); printf("\n正在等待对方链接,请稍等...\n"); if (SOCKET_ERROR == connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))) { printf("connect failed with error code: %d\n", WSAGetLastError()); closesocket(ClientSocket); WSACleanup(); MessageBox(NULL,TEXT("链接服务器失败!"),TEXT("Error"),MB_OK|MB_ICONWARNING); return -1; }else{ printf("链接成功...\n\n\n"); } char buffer[1024] = {0}; int iRecvLen = 0; int iSnedLen = 0; _beginthread(ThreadReceive, 0, NULL); //启动线程 iSnedLen = send(ClientSocket, name, strlen(name), 0); SendReceiveException(iSnedLen); while (1) { memset(buffer, 0, sizeof(buffer)); printf("My:"); gets(buffer); iSnedLen = send(ClientSocket, buffer, strlen(buffer), 0); SendReceiveException(iSnedLen); } closesocket(ClientSocket); WSACleanup(); printf("\n通讯结束!\n"); system("pause"); return 0; } void ThreadReceive(PVOID param) { char buffer[1024] = {0}; int iRecvLen = 0; char nameOther[32] = { 0 }; iRecvLen = recv(ClientSocket, nameOther, sizeof(nameOther), 0); SendReceiveException(iRecvLen); strcat(nameOther, "\0"); while(true) { memset(buffer, 0, sizeof(buffer)); iRecvLen = recv(ClientSocket, buffer, sizeof(buffer), 0); SendReceiveException(iRecvLen); strcat(buffer, "\0"); printf("\r \r【%s】:%s", nameOther,buffer); printf("\nMy:"); } } void SendReceiveException(int e) { if(SOCKET_ERROR == e) { printf("\n\nsend failed with error code: %d\n", WSAGetLastError()); printf("提示:链接异常或对方可能断开了链接!\n\n"); closesocket(ClientSocket); //关闭客户端套接字 WSACleanup(); //释放DLL MessageBox(NULL,TEXT("链接异常或对方可能断开了链接!"),TEXT("提示"),MB_OK|MB_ICONWARNING); system("pause"); exit(-1); } }
服务端代码(Server[32bit]V1.3.cpp)
#include <WinSock2.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <process.h> #include <windows.h> #pragma comment(lib,"ws2_32.lib") /* * * * * * * * * * * * * * * * Server * * * * * * * * * *夏雨程_YKC *alanlw21@qq.com * *Dev-C++5.11编译报错附加:-lwsock32 * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ typedef struct Client{ SOCKET ServerSocket; SOCKET ClientSocket01; SOCKET ClientSocket02; }CLS; int init(CLS *pSer); void CreatSocket(CLS *pcls); void ThreadStart(CLS *pcls); unsigned __stdcall ThreadReceive01(void* pCls); unsigned __stdcall ThreadReceive02(void* pCls); bool SendReceiveException(int e, CLS *p); char Tempbuffer1[1024] = {0}; char Tempbuffer2[1024] = {0}; int main(void) { system("title Server V1.3"); system("color 1E"); CLS cls; CLS *pcls = &cls; while(true) { init(pcls); CreatSocket(pcls); ThreadStart(pcls); } while(true); closesocket(pcls->ClientSocket01); closesocket(pcls->ClientSocket02); closesocket(pcls->ServerSocket); WSACleanup(); return 0; } int init(CLS *pSer) { SOCKADDR_IN ServerAddr = { 0 }; pSer->ServerSocket = INVALID_SOCKET; USHORT uPort = 47168; WSADATA wsaData = { 0 }; if (WSAStartup(MAKEWORD(2, 2), &wsaData)){ printf("WSAStartup failed with error code: %d\n", WSAGetLastError());system("pause"); return -1; } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){ printf("Version was not 2.2\n"); MessageBox(NULL,TEXT("Version was not 2.2(version Error)"),TEXT("Error"),MB_OK|MB_ICONWARNING); system("pause"); return -1; } pSer->ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (pSer->ServerSocket == INVALID_SOCKET) { printf("socket failed with error code: %d\n", WSAGetLastError()); MessageBox(NULL,TEXT("The initialization server failed!(socket function Error)"),TEXT("Error"),MB_OK|MB_ICONWARNING); system("pause"); return -1; } ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(uPort);//服务器监听端口 ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); if (SOCKET_ERROR == bind(pSer->ServerSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr))){ printf("bind failed with error code: %d\n", WSAGetLastError()); closesocket(pSer->ServerSocket);system("pause"); return -1; } if (SOCKET_ERROR == listen(pSer->ServerSocket, 3)) { printf("listen failed with error code: %d\n", WSAGetLastError()); closesocket(pSer->ServerSocket); WSACleanup();system("pause"); return -1; } } void CreatSocket(CLS *pcls) { pcls->ClientSocket01 = INVALID_SOCKET; pcls->ClientSocket02 = INVALID_SOCKET; SOCKADDR_IN ClientAddr01 = { 0 }; SOCKADDR_IN ClientAddr02 = { 0 }; printf("\nwaiting connect.....\n\n"); int ClientAddrLength01 = sizeof(ClientAddr01); int ClientAddrLength02 = sizeof(ClientAddr02); pcls->ClientSocket01 = accept(pcls->ServerSocket, (SOCKADDR*)&ClientAddr01, &ClientAddrLength01);//等待客户端1链接... printf("Client01 link to success, wait for Client02 link...\n"); pcls->ClientSocket02 = accept(pcls->ServerSocket, (SOCKADDR*)&ClientAddr02, &ClientAddrLength02);//等待客户端2链接... printf("Client02 link to success,Start connect.\n\n"); if (pcls->ClientSocket01 == INVALID_SOCKET || pcls->ClientSocket02 == INVALID_SOCKET) { printf("accept failed with error code: %d\n", WSAGetLastError()); closesocket(pcls->ServerSocket); WSACleanup();//释放dll资源 MessageBox(NULL,TEXT("接收两个客户端出错,请重启服务器!"),TEXT("Error"),MB_OK|MB_ICONWARNING); exit(-1); } } void ThreadStart(CLS *pcls) { HANDLE hThread01; HANDLE hThread02; unsigned threadID01;unsigned threadID02; printf("双方连接成功,开始聊天...\n\n"); hThread01 = (HANDLE)_beginthreadex( NULL, 0, &ThreadReceive01, pcls, 0, &threadID01 ); hThread02 = (HANDLE)_beginthreadex( NULL, 0, &ThreadReceive02, pcls, 0, &threadID02 ); WaitForSingleObject(hThread01, INFINITE); WaitForSingleObject(hThread02, INFINITE); CloseHandle(hThread01); CloseHandle(hThread02); } //线程1-客户端01 unsigned __stdcall ThreadReceive01(void* pCls) { int isError = 0; bool flag = true; CLS *p = (CLS*)pCls; char name[20] = { 0 }; isError = recv(p->ClientSocket01, name, sizeof(name), 0); if(SendReceiveException(isError, p))flag=false; isError = send(p->ClientSocket02, name, strlen(name), 0); if(SendReceiveException(isError, p))flag=false; printf("用户:%s---上线\n\n",name); while(flag) { memset(Tempbuffer1, 0, sizeof(Tempbuffer1)); isError = recv(p->ClientSocket01, Tempbuffer1, sizeof(Tempbuffer1), 0); if(SendReceiveException(isError, p))flag=false; strcat(Tempbuffer1, "\0"); printf("【%s】:%s\n",name,Tempbuffer1); isError = send(p->ClientSocket02, Tempbuffer1, strlen(Tempbuffer1), 0); if(SendReceiveException(isError, p))flag=false; } } //线程2-客户端02 unsigned __stdcall ThreadReceive02(void* pCls) { int isError = 0; bool flag = true; //判断错误 CLS *p = (CLS*)pCls; // 接收客户端02的用户名 char name[20] = { 0 }; isError = recv(p->ClientSocket02, name, sizeof(name), 0); if(SendReceiveException(isError, p))flag=false; isError = send(p->ClientSocket01, name, strlen(name), 0); if(SendReceiveException(isError, p))flag=false; printf("用户:%s---上线\n\n",name); while(flag) { memset(Tempbuffer2, 0, sizeof(Tempbuffer2)); isError = recv(p->ClientSocket02, Tempbuffer2, sizeof(Tempbuffer2), 0); if(SendReceiveException(isError, p))flag=false; strcat(Tempbuffer2, "\0"); printf("【%s】:%s\n",name,Tempbuffer2); isError = send(p->ClientSocket01, Tempbuffer2, strlen(Tempbuffer2), 0); if(SendReceiveException(isError, p))flag=false; } } bool SendReceiveException(int e, CLS *p) { if(SOCKET_ERROR == e) { printf("send failed with error code: %d\n", WSAGetLastError()); closesocket(p->ServerSocket); closesocket(p->ClientSocket01); closesocket(p->ClientSocket02); printf("\nException function:User disconnected or error,Close all Sockets!But no DLL file is freed.\n"); return true; } return false; }
此程序是在Dev-C++5.11下编译的,如果遇到报错:
则添加“-lwsock32”:
此错误参考
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。