并发性Socket通信源码(基于linux环境下多线程)

 

服务器端:server.c 

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <string.h>5 #include <arpa/inet.h>6 #include <pthread.h>7 void* working(void *arg);8 //信息结构体9 struct sockinfo10 {11     struct sockaddr_in addr;//用来存储地址信息12     int fd;//用来存储文件描述符13 };14 //创建一个信息数组,即同时支持与512个客户端进行通信,若想让其无上限,需要维护一个链表15 //在C++中可以维护一个STL16 struct sockinfo infos[512];17 int main()18 {19     //创建监听的套接字20     int lfd=socket(AF_INET,SOCK_STREAM,0);21     if(lfd==-1)22     {23         perror("socket");24         return -1;25     }26     struct sockaddr_in addr;27     addr.sin_family=AF_INET;28     addr.sin_port=htons(999);  //主机字节序转换为网络字节序,即小端字节序转换成为大端字节序29     addr.sin_addr.s_addr=INADDR_ANY;30     int ret=bind(lfd,(struct sockaddr*)&addr,sizeof(addr));31     if(ret==-1)32     {33         perror("bind");34         return -1;35     }36     //设置监听37     ret=listen(lfd,128);//设置最大监听数量为128个38     if(ret==-1)39     {40         perror("listen");41         return -1;42     }4344     //初始化结构数组45     int max=sizeof(infos)/sizeof(infos[0]);//计算数组的大小46     //将结构体数组中每个元素初始化为047     int i=0;48     for(i=0;i<max;++i)49     {50         bzero(&infos[i],sizeof(infos[i]));51         //memset(infos,0,sizeof(infos));52         //将结构体中的文件描述符修改为-153         infos[i].fd=-1;//通过文件描述符的值是否为-1来判断当前数组元素是否是被占用的5455     }5657     //阻塞并等待客户端的连接58     int clilen=sizeof(struct sockaddr_in);59     while(1)60     {61         struct sockinfo* pinfo;62         int i=0;63         for(i=0;i<max;++i)64         {65             if(infos[i].fd==-1)//此时说明该元素是可以使用的66             {67                 pinfo=&infos[i];68                 break;69             }70         }71         int cfd=accept(lfd, (struct sockaddr*)&pinfo->addr,&clilen);72         pinfo->fd=cfd;//保存返回的文件描述符73         if(cfd==-1)74         {75             perror("accept");76             break;77         }78         //与客户端建立连接后,需要与客户端进行通信。与客户端的通信需要一个子线程来连接79         //创建子线程80         pthread_t tid;81         pthread_create(&tid,NULL,working,pinfo);//pinfo就是需要传递给working函数的参数82         //任务执行完毕之后,子线程需要退出。此时,需要由主线程来释放子线程的资源83         //此时,需要调用detach()函数来使主线程与子线程进行资源分离84         pthread_detach(tid);85     }86     close(lfd);87     return 0;88 }8990 //子线程的任务函数·91 void* working(void *arg)92 {93     struct sockinfo* pinfo=(struct sockinfo*)arg;94     //打印客户端地址95     char ip[1024]={0};96     printf("客户端IP地址:%s,端口:%d\n",inet_ntop(AF_INET,&pinfo->addr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(pinfo->addr.sin_port));97     //和客户建立通信98     while(1)99     {
100         char buf[1024];
101         memset(buf,0,sizeof(buf));
102         int len=read(pinfo->fd,buf,sizeof(buf));
103         if(len>0)
104         {
105             printf("客户端say:%s\n",buf);
106             write(pinfo->fd,buf,len);
107         }
108         else if(len==0)
109         {
110             printf("客户端断开了连接...\n");
111             break;
112         }
113         else
114         {
115             perror("read");
116             break;
117         }
118     }
119     close(pinfo->fd);
120     pinfo->fd=-1;//将通信描述符再次初始化为-1
121     return NULL;
122 }

客户端:client.c

  1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <string.h>5 #include <arpa/inet.h>6 int main()7 {8     //创建监听的套接字9     int fd=socket(AF_INET,SOCK_STREAM,0);10     if(fd==-1)11     {12         perror("socket");13         exit(0);14     }15     struct sockaddr_in addr;16     addr.sin_family=AF_INET;17     addr.sin_port=htons(999);  //主机字节序转换为网络字节序,即小端字节序转换成为大端字节序18     inet_pton(AF_INET,"192.168.64.134",&addr.sin_addr.s_addr);19     int ret=connect(fd,(struct sockaddr*)&addr,sizeof(addr));20     if(ret==-1)21     {22         perror("connetc");23         exit(0);24     }25     //和服务器通信26     int number=0;27     while(1)28     {   //发送数据29         char buf[1024];30         sprintf(buf,"你好,服务器...%d\n",number++);31         write(fd,buf,strlen(buf)+1);32         //接收数据33         memset(buf,0,sizeof(buf));34         int len=read(fd,buf,sizeof(buf));35         if(len>0)36         {37             printf("服务器say:%s\n",buf);38             write(fd,buf,len);39         }40         else if(len==0)41         {42             printf("服务器断开了连接...\n");43             break;44         }45         else46         {47             perror("read");48             break;49         }50         sleep(1);51     }52     close(fd);53     return 0;54 }

编译:gcc server.c -lpthread -o server

           gcc client.c -lpthread -o client

启动运行:

                先运行服务器端./server,再运行客户端./client

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/113206.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《数据结构、算法与应用C++语言描述》-队列的应用-图元识别问题

《数据结构、算法与应用C语言描述》-队列的应用-图元识别问题 图元识别 问题描述 数字化图像是一个 mxm 的像素矩阵。在单色图像中&#xff0c;每一个像素要么为0&#xff0c;要么为 1。值为0的像素表示图像的背景。值为1的像素表示图元上的一个点&#xff0c;称其为图元像素…

BLUE引擎变量数据分析

今天跟大家说一下BLUE引擎的变量运用&#xff0c;以及使用中的小细节。大家在使用变量的时候&#xff0c;自定义变量不要以P、G、M、I、D、N、A开头。 变量与变量之间的常用格式: SMALL M88 <$STR(G88)> ;检测私人变量M88&#xff0c;是否小于全局变量G88 LARGE M88 &l…

Rust错误处理

返回值和错误处理 panic 深入剖析 主动调用 fn main() {panic!("crash and burn"); }backtrace 栈展开 panic 时的两种终止方式 当出现 panic! 时&#xff0c;程序提供了两种方式来处理终止流程&#xff1a;栈展开和直接终止 何时该使用 panic! 先来一点背景知…

分布式定时任务xxljob

xxl-job的xxl为作者名徐雪里拼音首字母。 xxl-job的作者是2015年开始开发这个项目&#xff0c;那时候springmvcbootstrapadminlte 大行其道&#xff0c;所以这个框架调度器一直沿用这个架构。 一、运行调度器 调度器可以集群或单点运行&#xff0c;以单点运行为例 下载代码…

前端 CSS 经典:box-shadow

1. 基础属性 /* box-shadow: h-shadow v-shadow blur spread color inset; */ box-shadow: 10px 10px 2px 2px red inset; h-shadow: 必填&#xff0c;水平阴影的位置&#xff0c;允许负值 v-shadow: 必填&#xff0c;垂直阴影的位置&#xff0c;允许负值 blur: 可选&#xff…

Linux shell编程学习笔记14:编写和运行第一个shell脚本hello world!

* 20231020 写这篇博文断断续续花了好几天&#xff0c;为了说明不同shell在执行同一脚本文件时的差别&#xff0c;我分别在csdn提供线上Linux环境 &#xff08;使用的shell是zsh&#xff09;和自己的电脑上&#xff08;使用的shell是bash&#xff09;做测试。功夫不负有心人&am…

视频怎么压缩?视频过大这样压缩变小

在日常生活中&#xff0c;我们常常会遇到需要压缩视频的情况&#xff0c;视频压缩不仅可以减小文件大小&#xff0c;方便存储和传输&#xff0c;还可以在保证质量的同时&#xff0c;满足不同的使用需求。那么&#xff0c;如何有效地压缩视频呢&#xff1f; 方法一&#xff1a;嗨…

集合根据属性分组思路

先创建结果结构&#xff0c;然后直接getOrDefault&#xff0c;最后put。 private Map<String, Map<String, ResourceBean>> covertResourceToMap(List<ResourceDto> resourceList) {// hotlineId,serviceCodeMap<String, Map<String, ResourceBean>…

Retrofit+Flow网络请求与Android网络请求的演变

Retrofit网络请求我想大家都不陌生&#xff0c;今天我就来梳理一下技术是如何一步一步进步&#xff0c;逼格是如何一步一步变高的。 Retrofit使用方式演变 萌新 刚开始接触Retrofit的时候是从okhttp和volley以及android系统源码里面那个HttpPost与HttpGet切换过来的。 publ…

GEO生信数据挖掘(九)肺结核数据-差异分析-WGCNA分析(900行代码整理注释更新版本)

第六节&#xff0c;我们使用结核病基因数据&#xff0c;做了一个数据预处理的实操案例。例子中结核类型&#xff0c;包括结核&#xff0c;潜隐进展&#xff0c;对照和潜隐&#xff0c;四个类别。第七节延续上个数据&#xff0c;进行了差异分析。 第八节对差异基因进行富集分析。…

Git 安装和基础命令、IDEA 基础操作

目录 总结命令&#xff1a;1、安装&#xff1a;1、安装2、配置环境变量&#xff1a; 2、Git操作&#xff1a;1、初始化&#xff1a;1、姓名邮箱&#xff1a;2、初始化仓库&#xff1a;3、工作区和暂存区分析 2、提交文件3、查看版本库状态4、安装小乌龟git不显示图标 5、查看提…

解线性方程组python实现迭代法(Jacobi迭代、Gauss-Seidel迭代、松弛迭代)

1. Jacobi迭代 Jacobi迭代法是一种用于求解线性方程组的迭代算法。它属于迭代法中的直接迭代法&#xff0c;通过不断迭代更新解向量来逼近线性方程组的解。 Jacobi迭代法的基本概念如下&#xff1a; 给定线性方程组的系数矩阵A和右侧常数向量b。 将系数矩阵A进行对角分解&…

解剖—单链表相关OJ练习题

目录 一、移除链表元素 二、找出链表的中间节点 三、合并两个有序链表 四、反转链表 五、求链表中倒数第k个结点 六、链表分割 七、链表的回文结构 八、判断链表是否相交 九、判断链表中是否有环(一) 十、 判断链表中是否有环(二) 注&#xff1a;第六题和第七题牛…

docker 基本用法-操作镜像

1.下载镜像 docker search centos #默认从 Docker Hub 中搜索镜像 访问 dockerhub&#xff1a;https://registry.hub.docker.com docker pull centos 拉取镜像 如果不能拉取 方法 1.需要配置配置镜像加速器 tee /etc/docker/daemon.json << EOF {"registry-mirro…

【文献copilot】调用文心一言api对论文逐段总结

文献copilot&#xff1a;调用文心一言api对论文逐段总结 当我读文献的时候&#xff0c;感觉读得太慢了&#xff0c;看翻译软件翻译的又觉得翻译的不好。于是我就写了个程序辅助我读文献&#xff0c;它可以逐段总结&#xff0c;输出格式是&#xff1a;原文一句话总结分段总结&a…

css钟表数字样式

如图&#xff1a; 代码 font-size: 28px;font-family: Yourname;font-weight: 500;color: #00e8ff;

CSS基础入门01

目录 1.CSS是什么 2.基本语法规范 3.引入方式 3.1内部样式表 3.2行内样式表 3.3外部样式 4.代码风格 4.1样式格式 4.2样式大小写 4.3空格规范 5.选择器 5.1选择器的功能 5.2选择器的种类 6.基础选择器 6.1标签选择器 6.2类选择器 6.3id 选择器 6.4通配符选择…

jQuery实现输入框提示并点击回显功能呢

html代码: <input type"text" id"affOrganization" name"affOrganization" class"form-control" placeholder"Search..." style"width: 300px" > <div class"search_suggest" id"gov_se…

黑豹程序员-架构师学习路线图-百科:开启分布式架构开发先河,让Java戴上全球第一的皇冠-EJB

文章目录 1、EJB的传奇2、什么是 EJB3、从拥抱到抛弃4、最终版EJB3.0 1、EJB的传奇 EJB这项技术其实已经消亡了&#xff0c;但为何我还专门单另拿出来讲呢&#xff1f;原因有三。 第一、EJB是J2EE雄霸全球的功臣&#xff0c;它把我们编程推向了分布式架构开发&#xff0c;为开…

Ubuntu的EFI分区无法删除

本文解决的问题&#xff1a;双系统装完后需要删除ubuntu的分区&#xff0c;但是EFI系统分区无法删除。 第一步&#xff1a;cmd中输入命令 diskpart 并回车&#xff0c;如图中①&#xff1b; 第二步&#xff1a;在弹出窗口②中依次输入如下命令即可删除EFI分区&#xff1b; /…