基于tcp和多线程的多人聊天室-C语言
之前在学习关于网络tcp和多线程的编程,学了知识以后不用一下总绝对心虚,于是就编写了一个基于tcp和多线程的多人聊天室。
具体的实现过程:
服务器端:绑定socket对象->设置监听数->等待连接->有客户端连接就新建一个线程,这个线程中,一旦就收到这个客户发送的消息,就广播的向其他客户端发送同样的消息。
客户端:向客户端连接->新建线程用来接收服务器端发送的消息,同时主进程用来发送消息
话不多说,直接上代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h> typedef struct sockaddr *sockaddrp; //存储客户端地址的结构体数组
struct sockaddr_in src_addr[];
socklen_t src_len = sizeof(src_addr[]); //连接后记录confd数组
int confd[] = {}; //设置连接人数
int count = ; void *broadcast(void *indexp)
{
int index = *(int *)indexp;
char buf_rcv[] = {};
char buf_snd[] = {};
//第一次读取用户姓名
char name[] = {};
int ret = recv(confd[index],name,sizeof(name),);
if( > ret)
{
perror("recv");
close(confd[index]);
return;
} while()
{
bzero(buf_rcv,sizeof(buf_rcv));
recv(confd[index],buf_rcv,sizeof(buf_rcv),); //判断是否退出
if( == strcmp("quit",buf_rcv))
{
sprintf(buf_snd,"%s已经退出悟空聊天室",name);
for(int i = ;i <= count;i++)
{
if(i == index || == confd[i])
{
continue;
} send(confd[i],buf_snd,strlen(buf_snd),);
}
confd[index] = -;
pthread_exit(); } sprintf(buf_snd,"%s:%s",name,buf_rcv);
printf("%s\n",buf_snd);
for(int i = ;i <= count;i++)
{
if(i == index || == confd[i])
{
continue;
} send(confd[i],buf_snd,sizeof(buf_snd),);
} } } int main(int argc,char **argv)
{
printf("悟空聊天室服务器端开始运行\n"); //创建通信对象
int sockfd = socket(AF_INET,SOCK_STREAM,);
if( > sockfd)
{
perror("socket");
return -;
} //准备地址
struct sockaddr_in addr = {AF_INET};
addr.sin_port = htons(atoi(argv[]));
addr.sin_addr.s_addr = inet_addr(argv[]); socklen_t addr_len = sizeof(addr); //绑定
int ret = bind(sockfd,(sockaddrp)&addr,addr_len);
if( > ret)
{
perror("bind");
return -;
} //设置最大排队数
listen(sockfd,); int index = ; while(count <= )
{
confd[count] = accept(sockfd,(sockaddrp)&src_addr[count],&src_len);
++count;
//保存此次客户端地址所在下标方便后续传入
index = count-; pthread_t tid;
int ret = pthread_create(&tid,NULL,broadcast,&index);
if( > ret)
{
perror("pthread_create");
return -;
} } }
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <string.h> typedef struct sockaddr *sockaddrp;
int sockfd; void *recv_other(void *arg)
{
char buf[]= {};
while()
{
int ret = recv(sockfd,buf,sizeof(buf),);
if( > ret)
{
perror("recv");
return;
}
printf("%s\n",buf);
}
} int main(int argc,char **argv)
{
if( != argc)
{
perror("参数错误");
return -;
} //建立socket对象
sockfd = socket(AF_INET,SOCK_STREAM,);
if( > sockfd)
{
perror("socket");
return -;
} //准备连接地址
struct sockaddr_in addr = {AF_INET};
addr.sin_port = htons(atoi(argv[]));
addr.sin_addr.s_addr = inet_addr(argv[]); socklen_t addr_len = sizeof(addr); //连接
int ret = connect(sockfd,(sockaddrp)&addr,addr_len);
if( > ret)
{
perror("connect");
return -;
} //发送名字
char buf[] = {};
char name[] = {};
printf("请输入您的昵称:");
scanf("%s",name);
ret = send(sockfd,name,strlen(name),);
if( > ret)
{
perror("connect");
return -;
} //创建接收子线程
pthread_t tid;
ret = pthread_create(&tid,NULL,recv_other,NULL); if( > ret)
{
perror("pthread_create");
return -;
}
//循环发送
while()
{
//printf("%s:",name);
scanf("%s",buf);
int ret = send(sockfd,buf,strlen(buf),);
if( > ret)
{
perror("send");
return -;
} //输入quit退出
if( == strcmp("quit",buf))
{
printf("%s,您已经退出了悟空聊天室\n",name);
return ;
} } }
client.c
将两份代码分别编译生成相应可执行文件,例如在Linux下server,client,然后先执行./server 端口号 ip ,再执行./client 端口号 ip就可以运行这个聊天室了。
总结:关于网络编程,tcp是一种连接方式的通信方式,两边一旦建立连接,就可以通过send和recv函数发送消息,比较的可靠,缺点是速度比较慢(相对于udp来说)。另外关于多线程编程方面,线程其实是一个进程的实体,是一个进程的组成部分,多个线程共享除了栈区以外的大部分区域,因此进程间的通信比较方便,这种方便带来的代价是,当多个进程同时去操作同一量时,容易造成不可预知的错误,因此就引入了互斥量(锁)的概念,互斥量的使用就保证了进程间通信的同步。
基于tcp和多线程的多人聊天室-C语言的更多相关文章
- 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室
原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- 66 网络编程(五)——TCP多线程实现多人聊天室
思路 客户端读写各一个类,可以使内部类,实现Runnable.读写类都与服务器端建立连接,一个收,一个发. 客户端实现接收和转发.多线程实现每个客户端的连接(使与各客户端的连接独立). 服务器端中创建 ...
- Python编写基于socket的非阻塞多人聊天室程序(单线程&多线程)
前置知识:socket非阻塞函数(socket.setblocking(False)),简单多线程编程 代码示例: 1. 单线程非阻塞版本: 服务端: #!/usr/bin/env python # ...
- 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室
原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端
java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端 启动界面如下图: 首先启动服务器: 客户端登陆,登陆成功后为: 默认发送是全部用户,是多人发送. 当在边列 ...
- 多人聊天室(Java)
第1部分 TCP和UDP TCP:是一种可靠地传输协议,是把消息按一个个小包传递并确认消息接收成功和正确才发送下一个包,速度相对于UDP慢,但是信息准确安全:常用于一般不要求速度和需要准确发送消息的场 ...
- Apache MiNa 实现多人聊天室
Apache MiNa 实现多人聊天室 开发环境: System:Windows JavaSDK:1.6 IDE:eclipse.MyEclipse 6.6 开发依赖库: Jdk1.4+.mina-c ...
- Python实现网络多人聊天室
网络多人聊天室 文件结构: chatroom ├── client.py # 客户端代码 ├── language.py # 语言文件 ├── server.py # 服务端代码 └── set ...
- Python实现网络多人聊天室 - Windows
项目名称:多人聊天室项目结构: client.py server.py settings.py项目思路:服务端接收客户端连接,客户端发送信息给服务端,服务端将信息发送给所有客户端.项目实现:主进程负责 ...
随机推荐
- 2017-2018-2 1723《程序设计与数据结构》实验四 & 实验五 & 课程总结 总结
作业地址 实验四作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1943 提交情况如图: 实验五作业:https://edu ...
- [系统软件]Ubuntu 18.04中的Shutter禁用了“编辑”选项解决
本文引用自linux公社, 原文请点击 : https://www.linuxidc.com/Linux/2018-04/151911.htm 在Ubuntu 18.04中安装了我最喜欢的截图工具 ...
- PAT 1008 数组元素循环右移问题
https://pintia.cn/problem-sets/994805260223102976/problems/994805316250615808 一个数组A中存有N(N>0)个整 ...
- PAT 1061 判断题
https://pintia.cn/problem-sets/994805260223102976/problems/994805268817231872 判断题的评判很简单,本题就要求你写个简单的程 ...
- Rabbitmq vs. kafka
https://mp.weixin.qq.com/s/2i_9TWoF3TsJvG6Dj_75vw http://www.cnblogs.com/valor-xh/p/6348009.html htt ...
- Vue的filter属性
Vue.filter('sss',function(data){ //可以使用逻辑处理数据 data += '123'; return data*10; }) new Vue({ el:'#app', ...
- Laravel 5.5 文档 ] 快速入门 —— 安装配置篇
服务器要求 Laravel 框架对PHP版本和扩展有一定要求,不过这些要求 Laravel Homestead 都已经满足了,不过如果你没有使用 Homestead 的话(那真是一件很遗憾的事情),有 ...
- [转帖]CR3,PDE,PTE,TLB 内存管理的简单说明
CR3,PDE,PTE,TLB Copy From https://www.cnblogs.com/zzSoftware/archive/2013/02/11/2908824.html 网上关于 ...
- hive存储、数据模型、内部表
创建内部表 加一列元素 删除表
- 设计模式笔记:适配器模式(Adapter)
1. 适配器模式简介 1.1 模式定义 适配器模式:通过一个类的接口转换成客户希望的另外一个接口,使原本由于接口不兼容而不能一起工作的那些类可以一起工作. 适配器从结构上分为:类适配器和对象适配器.其 ...