用socket实现一个多人聊天室的思路很简单,即在服务器端定义一个fd的int型数组,用来存储已经连接的客户端的socket连接套接字fd(因为发送和接收数据都只需要借助连接套接字fd),当服务器接收到来自某一客户端的数据时,直接转发给其他所有连接着的客户端,即完成了多人聊天室
服务器端:多线程进行数据的转发,记录聊天记录,向客户端发送进入退出聊天室提醒。
客户端:在主线程内发送数据,多线程接收其他客户端发的数据。输入“bye”退出客户端,

TCP.server
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#define PORT 4567
typedef struct
{
int fd;
char buff[100];
}MSG;
int sockfd;//服务器socket
int fds[10];//客户端的socketfd,10个元素,
int size =10 ;//用来控制进入聊天室的人数为10以内
char buf3[100] ={0};
typedef struct sockaddr SA;
typedef struct sockaddr_in SIN;
//给所有用户发送信息
void SendMsgToAll(MSG* msg)
{
MSG send_msg = *msg;

for (int i = 0;i < size;i++)
{if (fds[i] != 0){if(fds[i] == send_msg.fd)  continue;printf("sendto%d\n",fds[i]);send(fds[i],send_msg.buff,sizeof(send_msg.buff),0);FILE * fp = fopen("history.txt","a+");fwrite(send_msg.buff,strlen(send_msg.buff),1,fp);fclose(fp);}
}

}
//信息接收线程
void* service_thread(void* p)
{
int fd = (int)p;
printf(“pthread = %d\n”,fd);
while(1)
{
char buf[100] = {0};
memset(buf,0,100);
if (recv(fd,buf,sizeof(buf),0) <= 0) //当用户fd发生变化时遍历所有fd发送退出信息
{
int i;
for (i = 0;i < size;i++)
{
if (fd == fds[i])
{
fds[i] = 0;
break;
}
}
printf(“退出:fd = %dquit\n”,fd);
memset(buf3,0,100);
sprintf(buf3,"%s退出了聊天室",buf);
for (int i = 0;i < size;i++)
{
if (fds[i] != 0)
{
if(fds[i] == fd){
continue;
}
printf(“sendto%d\n”,fds[i]);
send(fds[i],buf3,strlen(buf3),0);

         }}memset(buf3,0,100);pthread_exit((void*)i);}
else
{if(strcmp(buf,"chat_history") == 0){memset(buf,0,100);FILE * fp = fopen("history.txt","r");//fseek(fp,0,SEEK_SET);fread(buf,1,100,fp);fclose(fp);send(fd,buf,sizeof(buf),0);memset(buf,0,100);continue;}//把服务器接受到的信息发给所有的客户端MSG msg_info;msg_info.fd = fd;strcpy(msg_info.buff,buf);SendMsgToAll(&msg_info);
}
}

}
//等待客户端连接
void service()
{
printf(“服务器启动,等待连接\n”);
while(1)
{
SIN fromaddr;
socklen_t len = sizeof(fromaddr);
int fd = accept(sockfd,(SA*)&fromaddr,&len);

    if (fd == -1){printf("客户端连接出错...\n");continue;}//记录客户端的socketint i = 0;for (i = 0;i < size;i++){if (fds[i] == 0){fds[i] = fd;printf("进入聊天室的fd:%d\n",fd);//有客户端连接之后,启动线程给此客户服务pthread_t tid;pthread_create(&tid,0,service_thread,&fd);break;}if (size == i){//发送给客户端说聊天室满了char* str = "对不起,聊天室已经满了!";send(fd,str,strlen(str),0); close(fd);}}
//提示用户上线
i = 0;
char buf2[20] = {0};
recv(fd,buf2,20,0);
sprintf(buf3,"%s进入了聊天室",buf2);for (i = 0;i < size;i++){if (fds[i] != 0){if(fds[i] == fd){continue;}printf("sendto%d\n",fds[i]);send(fds[i],buf3,strlen(buf3),0);}}
memset(buf3,0,100);
}

}

int main(int argc,char * argv[])
{
if(argc != 2)
{
printf(“命令格式错误\n”);
return -1;
}
//设置套接字
sockfd = socket(PF_INET,SOCK_STREAM,0);
if (sockfd == -1){
perror(“创建socket失败”);
exit(-1);
}
struct sockaddr_in addr;
addr.sin_family = PF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(argv[1]);
if (bind(sockfd,(SA*)&addr,sizeof(addr)) == -1){
perror(“绑定失败”);
exit(-1);
}
if (listen(sockfd,10) == -1){
perror(“设置监听失败”);
exit(-1);
}
service();
}

TCP.clint.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#define PORT 4567
int sockfd;//客户端socket
char name[20] = {0};//客户端姓名
typedef struct sockaddr SA;
//接收服务器转发的信息
void* recv_thread(void* p){
while(1){
char buf[100] = {};
if (recv(sockfd,buf,sizeof(buf),0) <= 0)
{
break;
}
printf("%s\n",buf);
}
}

void start()
{
//给服务器发送信息
pthread_t id;
pthread_create(&id,0,recv_thread,0);
char buf2[100] = {0};
send(sockfd,name,strlen(name),0);
while(1)
{
char buf[100] = {0};
scanf("%s",buf);
if (strcmp(buf,“bye”) == 0)
{
send(sockfd,name,(strlen(name)),0);
break;
}
else if(strcmp(buf,“chat_history”) == 0)
{
send(sockfd,buf,strlen(buf),0);
continue;
}
char msg[131] = {0};
sprintf(msg,"%s:%s",name,buf);
send(sockfd,msg,strlen(msg),0);
}
close(sockfd);
}
//主函数
int main(int argc,char * argv[])
{
//设置套接字
sockfd = socket(PF_INET,SOCK_STREAM,0);
struct sockaddr_in addr;
addr.sin_family = PF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(argv[1]);
//连接服务器
if (connect(sockfd,(SA*)&addr,sizeof(addr)) == -1)
{
perror(“无法连接到服务器”);
exit(-1);
}
printf(“客户端启动成功\n”);
printf(“请输入您的名字:”);
scanf("%s",name);
start();
return 0;
}

这个聊天室程序还有很多不足,1.发送数据不能识别空格;2.查找聊天室记录功能还需完善,现在只能显示前100个字符。如果还有其他不足的地方希望各位能提出来,以供其他阅读的人参考
希望能对各位有所帮助,同时希望各位大佬们能够完善。

linux网络编程TCP多人聊天室相关推荐

  1. 网络编程项目—— 多人聊天室->双人聊天

    一.Coding前的思考和步骤梳理 1. 又开始思考这个问题,拿到一个需求,是调用java底层的代码写1000行实现,还是直接调第三方库写50行实现? 都一样. 发现第一次写shell的时候其实思考过 ...

  2. java 多人聊天_java编程实现多人聊天室功能

    导读热词 本文实例为大家分享了java实现多人聊天室的具体代码,供大家参考,具体内容如下 程序源代码及运行截图: server.java //server.java package Socket; i ...

  3. TCP多人聊天室实现 JSON文件解析

    TCP多人聊天室实现 JSON文件解析 1. TCP多人聊天室实现 1.1 分析 客户端功能:1. 数据发送2. 数据接收技术:1. socket2. 输入流和输出流3. 多线程,客户端功能模块有两个 ...

  4. 网络编程基础_5.3聊天室-多人聊天室

    聊天室-多人聊天室 #include <stdio.h>// 1. 包含必要的头文件和库, 必须位于 windows之前 #include <WinSock2.h> #prag ...

  5. Linux 网络编程 TCP

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客 ...

  6. Linux网络编程——tcp并发服务器(poll实现)

    https://blog.csdn.net/lianghe_work/article/details/46535859 想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程--I/ ...

  7. java tcp多人聊天室

    TCP的多人聊天室 上次写了一个只能两个人通信的TCP,这次写了个可以多人聊天的,利用多线程实现. 设计模式: 服务端:首先运行服务器,然后启动一个专门处理客户端消息的线程,然后监听是否有客户端连接, ...

  8. Python中基于TCP网络通信协议的多人聊天室

    1.服务端设置 1.1 相关配置信息 便于后期维护修改,将数据协议的相关配置和服务器配置,以及登录验证的数据库信息单独建立一个.py文件.需根据自己服务器ip修改. #------数据协议相关配置-- ...

  9. 06 java GUI 网络编程:图形界面聊天室

    仿照第4篇笔记的形式,笔者决定将GUI和网络编程部分用综合练习的方式来总结.练习项目是有图形界面的聊天室,用到了GUI中的javax.swing包和网络编程中的TCP/socket编程.GUI部分的难 ...

最新文章

  1. 【二级java】排序技术
  2. Flutter开发之Debug调试(十)
  3. java 线程aba,JAVA中CAS-ABA的问题解决方案AtomicStampedReference
  4. C# 中打印、预览、打印机设置和打印属性的方法
  5. Leetcode: Kth Largest Element in an Array
  6. Windows2003 + SQL2000群集安装手册(DELL MD3000) 之MD3000 RAID配置方法(2)
  7. 什么题材的短视频最吸引人观看?
  8. Visual C# 2008+SQL Server 2005 数据库与网络开发-- 5.1 计算
  9. VMwareESX上的SCOM控制台无法正常运行
  10. word文字校对工具_如何在Word中使用校对面板
  11. IIS DirectoryEntry
  12. 一组NOKIA数据线电路图及制作图例
  13. 【FPGA】超声波测距
  14. 2019年8月23日 星期五(韩天峰的swoole)
  15. 云计算考证笔记、CPU虚拟化、内存虚拟化、IO虚拟化、存储虚拟化
  16. 16.集合框架(ArrayList,Vector,LinkedList,泛型(Generic),可变参数,增强for循环)
  17. 苹果开发者证与真机调试
  18. Nginx的配置与优化
  19. 系统日志Logrotate配置
  20. 【python爬虫】js逆向:空气质量在线平台,解决反调试,加密

热门文章

  1. 在微型计算机中 常见到,在微型计算机中,常见到的EGA、VGA等是指()。
  2. MoviePy,利用Python自动剪辑tiktok视频
  3. 井字棋 二维数组java_LeetCode 面试题 16.04. 井字游戏 Java
  4. 笔记本电脑无法U盘启动
  5. 【蓝图】p28-p29按键+鼠标点击实现开关门
  6. 矩阵期望 matlab,matlab中矩阵元素求和、求期望和均方差
  7. NetCMS修改之四:扩展轮换幻灯片属性(NorFilt),具有导读显示
  8. 本地配置hosts文件
  9. 2011年考研备战时间表
  10. NAB Show 2023新款云台摄像机“EX-Ultra R9”