前言

开发环境:Linux(ubuntu 12.04),GCC

编译:

gcc server.c -lpthread -std=gnu99 -o s
gcc client.c -lpthread -std=gnu99 -o c

相关知识:TCP(博客:传送门),线程

附加:项目可能还有写不足之处,有些bug没调出来(如:对在线人数的控制)。

效果图

运行服务端

运行2个客户端

其中一个客户端发送消息

互相发送

整体效果图

客户端发送"quit"断开连接。

代码下载

那么话不多说,放码过来:

码云:传送门,GitHub:传送门

代码

服务端:server.c

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>struct sockaddr_in addr = {};
int clifd_index = 0; // clifd的下标
char buf[1024] = {}; // 存储客户端发来的字符串
char str[1024] = {}; // 存储带clifd的回传信息
int clifd[30] = {}; // 存储clifd
int online_num = 0;    // 连接人数
int max_num = 10; // 最大人数// 项目有bug,连接人数的限制控制不住,有待改进void* start_read(void *arg) // 读取信息的子线程
{
//  printf("arg:%d\n",*(int*)arg);int clifd1 = *(int*)arg;printf("run_clifd:%d\n",clifd1);for(;;){
//      printf("before read\n");int ret = read(clifd1,buf,sizeof(buf));printf("\nip:%s,port:%hu,size:%d\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port),ret); // 获取相关信息printf("say:%s\n",buf);char id[10] = {};sprintf(id,"%d说:",clifd1);if(strlen(buf) != 0){strcpy(str,id);strcat(str,buf);} // 存入str中if(0 == strcmp("quit",buf)) // 如果收到quit{online_num--; // 在线人数-1for(int i=0; i<clifd_index; i++){if(clifd1 == clifd[i]){int *die = &clifd1;clifd[i] = 0;pthread_exit(die); // 终止线程break;}}}//usleep(1000);}
}void* start_write(void *arg) // 写回的子线程
{
//  printf("arg:%d\n",*(int*)arg);//  usleep(500);int clifd1 = *(int*)arg;printf("run_clifd:%d\n",clifd1);for(;;){int flag = 0;for(int i=0; i<clifd_index; i++) // 因为读到quit的原因,clifd被置0{if(clifd1 == clifd[i]){break;}if(i == clifd_index-1){int *die = &clifd1;flag = 1;pthread_exit(die); // 终止此写回的子线程}}if(flag == 1){break;}if(strlen(str) == 0) // 空消息不写入continue;printf("before write\n");printf("str:%s\n",str);write(clifd1,str,strlen(str)+1);usleep(50000); // 最快的子线程等待其他子线程memset(str,0,1024); // 清空str}
}int main()
{printf("服务器创建socket...\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(0 > sockfd){perror("socket");return -1;}printf("准备地址...\n");addr.sin_family = AF_INET;addr.sin_port = htons(6008);//端口号addr.sin_addr.s_addr = inet_addr("127.0.0.1");//你的ip地址(或服务器的私网ip)socklen_t len = sizeof(addr);printf("绑定socket与地址...\n");if(bind(sockfd,(struct sockaddr*)&addr,len)){perror("bind");return -1;}printf("设置监听...\n");if(listen(sockfd,2)){perror("listen");return -1;}printf("等待客户端连接...\n");for(;;){if(online_num < max_num){struct sockaddr_in addrcli = {};clifd[clifd_index] = accept(sockfd,(struct sockaddr*)&addrcli,&len);int flag = 0;for(int i=0; i<clifd_index; i++){if(clifd[clifd_index] == clifd[i]){flag = 1;break;}}if(flag == 1){clifd_index--;continue;}else{char link[50] = {};char link1[40] = "您已经成功连接";sprintf(link,"您的id是:%d,",clifd[clifd_index]);strcat(link,link1);write(clifd[clifd_index],link,strlen(link)+1);online_num++;}}else{continue;}if(0 > clifd[clifd_index]){perror("accept");continue;}printf("clifd:%d\n",clifd[clifd_index]);// 创建子线程pthread_t pid1,pid2;pthread_create(&pid1,NULL,start_read,&clifd[clifd_index]);pthread_create(&pid2,NULL,start_write,&clifd[clifd_index]);usleep(1000);//        printf("clifd:%d\n",clifd[index]);clifd_index++; // 下标逐渐+1,这样写不是很合适}return 0;
}

客户端:client.c

#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>void* start_read(void* arg) // 读取信息
{int sockfd = *(int*)arg;char buf[1024] = {};for(;;){read(sockfd,buf,sizeof(buf));if(strlen(buf) != 0){printf("\n>%s\n",buf);}}
}int main()
{printf("服务器创建socket...\n");int sockfd = socket(AF_INET,SOCK_STREAM,0);if(0 > sockfd){perror("socket");return -1;}printf("准备地址...\n");struct sockaddr_in addr = {};addr.sin_family = AF_INET;addr.sin_port = htons(6008);//设置的端口号addr.sin_addr.s_addr = inet_addr("127.0.0.1");//你的ip地址(或服务器的公网ip)socklen_t len = sizeof(addr);printf("绑定连接服务器...\n");if(connect(sockfd,(struct sockaddr*)&addr,len)){perror("connect");return -1;}char link[50] = {};read(sockfd,link,sizeof(link));
//  printf("link:%s\n",link);if(strstr(link,"您已经成功连接")==NULL){printf("连接人数已满,请稍后重试\n");return 0;}else{printf("link:%s\n",link);}// 创建读取子线程pthread_t pid;pthread_create(&pid,NULL,start_read,&sockfd);for(;;){char buf[1024] = {};usleep(1000);//printf(">我说:");gets(buf);write(sockfd,buf,strlen(buf)+1);if(0 == strcmp("quit",buf)){printf("通信结束!\n");break;}}close(sockfd);
}

Linux下c语言TCP多线程聊天室相关推荐

  1. c语言tcp多线程聊天室,66 网络编程(五)——TCP多线程实现多人聊天室

    思路 客户端读写各一个类,可以使内部类,实现Runnable.读写类都与服务器端建立连接,一个收,一个发. 客户端实现接收和转发.多线程实现每个客户端的连接(使与各客户端的连接独立). 服务器端中创建 ...

  2. c语言tcp多线程聊天,基于tcp和多线程的多人聊天室-C语言

    之前在学习关于网络tcp和多线程的编程,学了知识以后不用一下总绝对心虚,于是就编写了一个基于tcp和多线程的多人聊天室. 具体的实现过程: 服务器端:绑定socket对象->设置监听数-> ...

  3. Linux下Select多路复用实现简易聊天室

    前言 和之前的udp聊天室有异曲同工之处,这次我们客户端send的是一个封装好了的数据包,recv的是一个字符串,服务器recv的是一个数据包,send的是一个字符串,在用户连接的时候发送一个logi ...

  4. Linux以下基于TCP多线程聊天室(client)

    不怎么会弄这个博客的排版,就直接将代码附上: 主要是使用多线程去等待接受数据和发送数据.以下是client的代码: tcpsed.h文件 1234567891011121314151617181920 ...

  5. Linux下C语言实现多线程排序文件内容

    一.要求及主要函数 使用多线程,编写一个并行程序,将目录中的多个文件里的内容进行排序. 文件内容格式为: <数字><空格><数字> 例如: 0 1 2 3 4 5 ...

  6. linux下c语言tcp文件传输,C语言实现TCP通信

    导读 如果想要自己写一个服务器和客户端,我们需要掌握一定的网络编程技术,个人认为,网络编程中最关键的就是这个东西--socket(套接字).socket(套接字):简单来讲,socket就是用于描述I ...

  7. 利用多线程实现linux下C语言的聊天室程序:

    转载:http://www.360doc.com/content/16/0421/11/478627_552531090.shtml 利用多线程实现linux下C语言的聊天室程序: 客户端代码: th ...

  8. Linux下C语言编程

    第1章 Linux下C语言编程简介 本章将简要介绍一下什么是Linux,C语言的特点,程序开发的预备知识,Linux下C语言开发的环境,程序设计的特点和原则以及编码风格等.通过本章的学习,可以对在Li ...

  9. 初识Linux下C语言编程

    本章将简要介绍一下什么是Linux,C语言的特点,程序开发的预备知识,Linux下C语言开发的环境,程序设计的特点和原则以及编码风格等.通过本章的学习,可以对在Linux下使用C语言编程有一个基本的了 ...

最新文章

  1. 只要可能,就缓存数据和页输出
  2. PHP基础封装简单的MysqliHelper类
  3. floyd 判圈算法 UVa 11549 计算器谜题
  4. 获取项目版本号与设置引导页的判断条件
  5. python 怎么报错后再次启动?
  6. 字符串排序java_利用Java程序将字符串进行排序与拼接
  7. 跟我一起创建一个简单的javascript ajax对象 ---献给Web开发初学者
  8. 天眼探空经济发展_“天眼”探空惊艳全球
  9. js把txt转为html,js格式化文本为html标签
  10. 微软开启imap服务器,连接到 IMAP 或 SMTP 服务器
  11. java 验证是否为省份证号 详细验证 验证月份 日期等 要素
  12. 开源音乐播放器_测试4个开源音乐播放器等
  13. 解决创建文本文件,修改后缀为.py,仍改不了文本类型的问题
  14. C++ 完全平方数
  15. 实战项目:Boost搜索引擎
  16. Python十分钟轻松入门
  17. C#时间显示格式(12小时制VS24小时制)
  18. 安全认证宇宙之用户认证0x01
  19. java linux 读取文件内容_java访问Linux服务器读取文件
  20. 微信小程序直传腾讯云COS并对图片持久化文字水印案例

热门文章

  1. win10电脑垃圾广告怎么删除
  2. Hum Brain Mapp | 联合连接矩阵独立成分分析:结构和功能连接的自动链接
  3. Ardunio单片机读取HKH-11C呼吸传感器(并通过电脑串口打印)
  4. 常见英文缩写及相应中文
  5. html js 延迟加载,JS延迟加载方法
  6. 整理软件工程最基本的几个概念
  7. Delphi类似QQ皮肤控件,欢迎试用!
  8. 2017-2018-2 20179207 《网络攻防技术》第二周作业
  9. Python零基础小白的兼职月入过万,推荐个最靠谱的接单网站
  10. XMETA受邀参加迪拜MetaWeek2022,共探元界的发展与未来