多线程实现 qq 群聊的服务端和客户端

编程入门 行业动态 更新时间:2024-10-25 10:27:35

<a href=https://www.elefans.com/category/jswz/34/1767532.html style=多线程实现 qq 群聊的服务端和客户端"/>

多线程实现 qq 群聊的服务端和客户端

效果比较简陋,但是功能可以实现
效果:

服务器

#include <iostream>
#include <winsock2.h>//必须写在windows.h前面
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")#define MAX_CLI 256
#define Max_Buf_Size 1024SOCKET cliSocket[MAX_CLI];
int cliCount = 0;
HANDLE hMutex;//打印错误
void ErrorHanding(const char* msg)
{fputs(msg, stderr);fputc('\n', stderr);exit(1);
}//发数据
void SendMsg(SOCKET currScoker, const char* msg)
{WaitForSingleObject(hMutex, INFINITE);for (int i = 0; i < cliCount; i++){if (currScoker != cliSocket[i]){send(cliSocket[i], msg, strlen(msg), 0);}}ReleaseMutex(hMutex);
}//每个客户端单独线程管理
DWORD WINAPI Thread_Client(void* client)
{SOCKET currCli = *(SOCKET*)client;char recvBuf[Max_Buf_Size] = { 0 };while (true){int iLen = recv(currCli, recvBuf, Max_Buf_Size, 0);if (iLen!=-1){SendMsg(currCli,recvBuf);}else{break;}}WaitForSingleObject(hMutex, INFINITE);bool isdel = false;for (int i =0;i<cliCount;i++){if (cliSocket[i] == currCli || isdel){while (i++<cliCount){cliSocket[i] = cliSocket[i + 1];}break;}}cliCount--;ReleaseMutex(hMutex);closesocket(currCli);return  0;
}int main() 
{printf("TCP Server\n");//0 初始化网络库 // 加载套接字库WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD(2, 2);//初始化套接字库err = WSAStartup(wVersionRequested, &wsaData);if (err != 0){ErrorHanding("WSAStartup Error");}if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();ErrorHanding("LOBYTE HIBYTE Error");}//创建互斥对象hMutex = CreateMutex(NULL, false, NULL);//1.SOCKET 创建SOCKET socksrv = socket(AF_INET, SOCK_STREAM, 0);if (socksrv == SOCKET_ERROR){ErrorHanding("SOCKET Error");}//2.分配IP端口和绑定IP端口SOCKADDR_IN addrsrv;addrsrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//htonl用来将主机字节顺序转换为网络字节顺序;addrsrv.sin_family = AF_INET;addrsrv.sin_port = htons(6666);//htons用来将主机字节顺序转换为网络字节顺序;if (bind(socksrv, (SOCKADDR*)&addrsrv, sizeof(SOCKADDR)) == SOCKET_ERROR){ErrorHanding("bind Error");}if (listen(socksrv, MAX_CLI) == SOCKET_ERROR){ErrorHanding("socksrv Error");}SOCKADDR_IN addrcli;int len = sizeof(addrcli);while (true){//4.分配分机去处理服务器连接SOCKET cli =accept(socksrv, (SOCKADDR*)&addrcli, &len);WaitForSingleObject(hMutex,INFINITE);cliSocket[cliCount++] = cli;printf("ip=%s,num=%d", inet_ntoa(addrcli.sin_addr), cliCount);ReleaseMutex(hMutex);CreateThread(NULL, 0, Thread_Client, &cli, 0, NULL);}//8.关闭总机closesocket(socksrv);WSACleanup();return 0;
}

客户端

#include <iostream>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")#define Max_Buf_Size 1024
#define Max_Name 256char szMsg[Max_Buf_Size];
char szName[Max_Name] = "[DEFAULT]";//打印错误
void ErrorHanding(const char* msg)
{fputs(msg, stderr);fputc('\n', stderr);exit(1);
}DWORD WINAPI RecvMsg(void* socketcli)
{char recvBuf[Max_Buf_Size + Max_Name] = { 0 };while (true){memset(recvBuf, 0, Max_Buf_Size + Max_Name);int iLen = recv(*(SOCKET*)socketcli, recvBuf, Max_Buf_Size + Max_Name - 1, 0);if (iLen == -1){return -1;}recvBuf[iLen] = 0;fputs(recvBuf, stdout);}return 0;
}DWORD WINAPI SendMsg(void* socketcli)
{char sendBuf[Max_Buf_Size + Max_Name] = { 0 };do //如果控制台输入q加回车则下线{memset(szMsg, 0, Max_Buf_Size);//初始化消息fgets(szMsg, Max_Buf_Size, stdin);//等待控制台输入,并赋值消息if (strcmp(szMsg, "Q\n") && strcmp(szMsg, "q\n")){sprintf_s(sendBuf, "%s:%s", szName, szMsg);}else{sprintf_s(sendBuf, "%s:已下线", szName);}send(*(SOCKET*)socketcli, sendBuf, Max_Buf_Size, 0);}while (strcmp(szMsg, "Q\n") && strcmp(szMsg, "q\n"));return 0;
}int main(int count, char* c_arg[])
{if (count != 2){puts("必须输入两个参数才能开启聊天室(程序和人物昵称)");puts("启动方式:在程序运行目录下 shift + 鼠标右键 选择powershell打开");puts("例如:./MyTreadClient.exe WXR");system("pause");return -1;}sprintf_s(szName, "%s", c_arg[1]);//将数据格式化输出到字符串,给人物昵称赋值puts("聊天室");//0 初始化网络库 // 加载套接字库WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD(2, 2);//初始化套接字库err = WSAStartup(wVersionRequested, &wsaData);if (err != 0){ErrorHanding("WSAStartup Error");}if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();ErrorHanding("LOBYTE HIBYTE Error");}//1.SOCKET 创建SOCKET socksrv = socket(AF_INET, SOCK_STREAM, 0);if (socksrv == SOCKET_ERROR){ErrorHanding("SOCKET Error");}//2.分配IP端口和绑定IP端口SOCKADDR_IN addrsrv;addrsrv.sin_addr.S_un.S_addr = inet_addr("192.168.0.104");addrsrv.sin_family = AF_INET;addrsrv.sin_port = htons(6666);if (connect(socksrv, (SOCKADDR*)&addrsrv, sizeof(SOCKADDR_IN)) == SOCKET_ERROR){ErrorHanding("connect Error");}HANDLE threadAry[2];threadAry[0] = CreateThread(NULL, 0, RecvMsg, &socksrv, 0, NULL);threadAry[1] = CreateThread(NULL, 0, SendMsg, &socksrv, 0, NULL);WaitForMultipleObjects(2, threadAry, true, INFINITE);closesocket(socksrv);WSACleanup();return 0;
}

更多推荐

多线程实现 qq 群聊的服务端和客户端

本文发布于:2023-07-01 05:37:32,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/971473.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:多线程   服务端   客户端   qq

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!