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

服务器

#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 群聊的服务端和客户端相关推荐

  1. 多线程+SOCKET编程实现qq群聊的服务端和客户端

    多线程+SOCKET编程实现qq群聊的服务端和客户端 标签(空格分隔): 多线程 网络编程 线程同步 一.设计思路 1.服务端 每来一个客户端连接,服务端起一个线程维护: 将收到的消息转发给所有的客户 ...

  2. 用C语言写一个通信软件,客户端可以实现文字聊天,文件传输,建立群聊;服务端可以创建账号吧...

    首先,需要为客户端和服务端分别编写代码,客户端的代码应该包括实现文字聊天.文件传输和建立群聊的功能,而服务端的代码则需要实现创建账号的功能.需要考虑到网络的安全性.客户端的用户体验以及服务端的可扩展性 ...

  3. Java项目模拟QQ群聊和私聊(网络编程+多线程)

    [文末获取资源] 前几天学习了多线程,最近在学习网络编程,了解了UDP之后又学习了TCP,听一下大佬说,要看看你这两个东西掌握的怎么样,最好的办法就是写一个模拟QQ群聊和私聊,经过这几天的学习,以及不 ...

  4. php仿qq群聊,用Python写一个类似qq群聊的聊天室

    用Python写一个聊天室 功能 : 类似qq群聊 1. 进入聊天室需要输入姓名,姓名不能重复 2. 有人进入聊天室会向其他人发送通知 xxx 进入了聊天室 3. 一个人发消息,其他人会收到消息 xx ...

  5. 基于python实现类似qq群聊功能

    这篇文章主要记录了自己学习python时学习到的使用python来实现类似qq群聊的功能,整个项目分为服务器端和客户端两个部分,具体的实现如下: 一.具体代码 1.服务器端(Server.py) im ...

  6. 模拟QQ聊天小项目收尾---界面展示服务端与客户端进行信息交互(用到的知识:io,线程,Swing界面,面向对象思想...... )

    大家好,我是一位在java学习圈中不愿意透露姓名并苟且偷生的小学员,如果文章有错误之处,还望海涵,欢迎多多指正 如果你从本文学到有用的干货知识,那么请您尽量点赞,关注,评论,收藏 这两天我一直在设计这 ...

  7. OSI七层、TCP/IP五层、UDP、TCP的socket编程(服务端及客户端)、字节序转换、多进程以及多线程服务端的实现

    1.网络以覆盖范围划分:局域网/城域网/广域网   互联网/因特网   以太网/令牌环网--组网方式 2.在网络中必须能够为一表示每一台主机,才能实现点到点的精确通信            IP地址: ...

  8. qq群聊机器人接入ChatGPT-简介和源码

    qq群聊机器人接入ChatGPT 最近 ChatGPT 很火,也注册了账号玩了玩,确实灰常强大.但是也有的小伙伴可能没办法注册账号,我就想着把qq群机器人接入ChatGPT. 过程还是比较简单顺利的. ...

  9. DotNetty系列六:将服务端和客户端改为Winform窗口,使用Redis做为缓存,实现用户登录,好友,群组上下线显示。

    这次改动挺大的. 1.服务端和客户端改为Winform窗口.好多细节未处理,只是实现了功能.     2.使用Redis做为缓存,版本redis-3.0.1,和RedisDesktopManager做 ...

最新文章

  1. curl: (25) Failed FTP upload: 550 解决办法
  2. kettle中job给转换配置相对路径
  3. C#Winform怎么让控件随着主界面大小变化
  4. 玩转mini2440开发板之【在Ubuntu 14.04下编译安装tslib 1.4版本】
  5. python 读中文乱码_python字符乱码的解决小结
  6. c++ list容器获取第n给元素_Java总结之容器家族--Collection*
  7. php中的rand,php rand() 随机数生成的方法介绍
  8. jsf2.0---jsf的新特性
  9. nvme分区选mbr还是guid_[Win] 最强大的磁盘分区工具 DiskGenius v5.1.1 中文专业破解版...
  10. 服务器实体机与虚拟机,八种虚拟机与实机之间数据交互的方法|虚拟机与实体机之间的互连与数据交换方法...
  11. 计算机语言中str是什么意思,vb中str什么意思
  12. 第四讲 身份认证技术
  13. tftpd32服务器软件在Windows与linux 下的文件传输
  14. 与Lucene 4.10配合的中文分词比较(转)
  15. 小游戏3366HTML5小游戏,Canvas小游戏——五子棋
  16. JDK1.8.0_181安装以及环境配置教程(Win10系统)
  17. linux查看linux版本,内核版本,系统位数,gcc版本,Ubuntu下查看linux版本,内核版本,系统位数,gcc版本...
  18. 0315 财经爬虫实战
  19. 小程序服务器与系统维护协议,小程序后台维护
  20. 打开命令行窗口的方式

热门文章

  1. WPFLoading遮层罩
  2. Keras : 利用卷积神经网络CNN对图像进行分类,以mnist数据集为例建立模型并预测
  3. 刷脸自助登记 访客管理不再潦草应对!
  4. Ureport2小计和合计功能
  5. 倍福--控制汇川伺服无法使能分析
  6. python爬取公众号文章数据库,爬取微信公众号所有文章的请教
  7. 什么是迭代(die dai)
  8. PTA 背包问题凑零钱
  9. 微信读书登陆界面java_(JAVA后端)微信小程序-毕设级项目搭建-微信阅读小程序(内含源码,微信小程序+java逻辑后台+vue管理系统)~不求完美,实现就好...
  10. 推荐与广告 中的概念和指标