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

news2024/12/23 23:41:10

 

服务器端: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 sockinfo
 10 {
 11     struct sockaddr_in addr;//用来存储地址信息
 12     int fd;//用来存储文件描述符
 13 };
 14 //创建一个信息数组,即同时支持与512个客户端进行通信,若想让其无上限,需要维护一个链表
 15 //在C++中可以维护一个STL
 16 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     }
 43
 44     //初始化结构数组
 45     int max=sizeof(infos)/sizeof(infos[0]);//计算数组的大小
 46     //将结构体数组中每个元素初始化为0
 47     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         //将结构体中的文件描述符修改为-1
 53         infos[i].fd=-1;//通过文件描述符的值是否为-1来判断当前数组元素是否是被占用的
 54
 55     }
 56
 57     //阻塞并等待客户端的连接
 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 }
 89
 90 //子线程的任务函数·
 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         else
 46         {
 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.coloradmin.cn/o/1118039.html

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

相关文章

烘焙蛋糕外卖小程序商城的作用是什么

随着经营成本上升及电商业态的冲击&#xff0c;传统烘焙蛋糕门店商家经营止步不前&#xff0c;加之口罩原因更是雪上加霜&#xff0c;引流拓客、经营转化复购大幅度降低&#xff0c;而线上又因外卖平台间的激烈竞争&#xff0c;导致中小烘焙蛋糕商家进退两难。 烘焙蛋糕店经营…

PO模式在selenium自动化测试框架的优势

大家都知道po模式可以提高代码的可读性和减少了代码的重复&#xff0c;但是相对的缺点还有&#xff0c;今天通过本文一起学习下PO模式在selenium自动化测试框架的优势&#xff0c;需要的朋友可以参考下 PO模式简介 1.什么是PO模式 PO模型是:Page Object Model的简写 页面对象…

使用 Sealos 一键私有化部署 Serverless 框架 Laf

太长不看&#xff1a;Laf 上架了 Sealos 的模板市场&#xff0c;通过 Laf 应用模板即可一键部署&#xff01; Laf 是一个完全开源的项目&#xff0c;除了使用公有云之外&#xff0c;还有大量的用户选择私有化部署 Laf。然而&#xff0c;私有化部署通常伴随着更多的复杂性和门槛…

java 实现定时任务

1、EnableScheduling spring自带的定时任务功能&#xff0c;使用比较简单方便&#xff1a; 1、需要定时执行的方法上加上Scheduled注解&#xff0c;这个注解中可以指定定时执行的规则&#xff0c;稍后详细介绍。 2、Spring容器中使用EnableScheduling开启定时任务的执行&…

解决找不到VCRUNTIME140_ 1.dll问题的5个方法分享

近日&#xff0c;许多用户在运行某些软件时遇到了“由于找不到VCRUNTIME140_1.dll无法继续执行此代码”的问题。这个错误通常出现在运行某些软件或游戏时&#xff0c;提示找不到必要的动态链接库文件。本文将详细VCRUNTIME140_ 1.dll文件是什么&#xff0c;并分享如何解决这个问…

1658.将x减到0的最小操作数(滑动窗口)

目录 一、题目 二、分析代码 一、题目 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 二、分析代码 class Solution { public:int minOperations(vector<int>& nums, int x) {int _MaxLength INT_MIN;int _sum 0;int tmp 0;for (aut…

数据回归算法 | Python逻辑回归

逻辑回归是一种经典的机器学习算法,用于解决二分类问题。 它常被用于预测某个事件发生的概率,通过将输入特征映射到一个概率值来进行分类。 简单聊聊 逻辑回归就像一位智能的侦探,根据一些线索(输入特征)判断某件事情是否会发生。 它将这些线索组合起来,计算出一个关于…

洛谷 P1216 [USACO1.5] [IOI1994]数字三角形题解

观察题目我们发现从前往后推会有条件判断&#xff0c;不容易写出来。所以就从后往前推。 也就是说后面的状态已经是推出来了&#xff0c;保证是最大值。 //数字三角形 #include<iostream> using namespace std; const int N 510; int f[N][N], n;int main() {ios::sync…

利用Bootstrap的面包屑组件实现面包屑层次分级导航效果

目录 01-相关基础知识02-一个简单的示例03-改变面包悄中的层级分隔符 01-相关基础知识 可以用类breadcrumb实现面包屑层次导航效果。 当使用 Bootstrap 构建网页时&#xff0c;breadcrumb 类用于创建面包屑导航&#xff08;breadcrumb navigation&#xff09;&#xff0c;这是…

在 RN 中构建自适应 UI

移动开发的世界在不断变化&#xff0c;随之而来的是对能够适应任何设备或方向的用户界面的需求。React Native 提供了一套丰富的工具来构建这样的需求。 在本文中&#xff0c;我们将探讨如何在 React Native 中设计响应式和自适应 UI&#xff0c;重点关注不同的设备尺寸、方向…

yakit使用爆破编码明文_dnslog使用

yakit使用爆破编码密码 文章目录 yakit使用爆破编码密码yakit使用1 yakit编码密码进行爆破2 准备eval.php文件放入web3 访问http://192.168.225.206/eval.php,使用bp抓包,测试后环境准本好4 使用yakit4.1 进入页面&#xff0c;点击这里进行配置默认端口80834.2 发送到模糊测试4…

Qt 官方文档及阅读方法

文章目录 选择 All Qt Modules 查找模块选择 C Classes 查看该模块的所有的类当前类说明文档 QT 官方文档参考&#xff1a;https://doc.qt.io/qt-5 选择 All Qt Modules 查找模块 选择 C Classes 查看该模块的所有的类 当前类说明文档 包括 属性公共函数重新实现的公共功能公…

如何正确停止线程?为什么 volatile 标记位的停止方法是错误的?

Java全能学习面试指南&#xff1a;https://javaxiaobear.cn 今天我们主要学习如何正确停止一个线程&#xff1f;以及为什么用 volatile 标记位的停止方法是错误的&#xff1f; 首先&#xff0c;我们来复习如何启动一个线程&#xff0c;想要启动线程需要调用 Thread 类的 start…

面试官:说说 HTTP 常见的请求头有哪些?

一、是什么 HTTP头字段&#xff08;HTTP header fields&#xff09;,是指在超文本传输协议&#xff08;HTTP&#xff09;的请求和响应消息中的消息头部分 它们定义了一个超文本传输协议事务中的操作参数 HTTP头部字段可以自己根据需要定义&#xff0c;因此可能在 Web 服务器…

想要精通算法和SQL的成长之路 - 找到最终的安全状态

想要精通算法和SQL的成长之路 - 找到最终的安全状态 前言一. 找到最终的安全状态1.1 初始化邻接图1.2 构建反向邻接图1.3 BFS遍历1.4 完整代码 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 找到最终的安全状态 原题链接 我们从题目中可以看出来&#xff1a; 出度为0的…

如何用python做简单的接口压力测试

这篇文章主要介绍了如何用python做简单的接口压力测试问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教− 最近研究了一下接口的压力测试&#xff0c;主要来说就是连续频繁的对接口的调用&#xff0c;来测试接口的响应速度、返回结果&#…

Docker systemctl 安装配置

在docker中使用systemctl的时候&#xff0c;发现没有这个命令&#xff0c;我也去网上找了一些资料&#xff0c;很多都说在docker run的时候设置一些参数&#xff0c;/init 类似这些&#xff0c;但是都没效果。后来找了一些资料&#xff0c;自己尝试了&#xff0c;成功了。 1.下…

抛砖引玉:Redis 与 接口自动化测试框架的结合

接口自动化测试已成为保证软件质量和稳定性的重要手段。而Redis作为一个高性能的缓存数据库&#xff0c;具备快速读写、多种数据结构等特点&#xff0c;为接口自动化测试提供了强大的支持。勇哥这里粗略介绍如何结合Python操作Redis&#xff0c;并将其应用于接口自动化测试框架…

EasyRule源码:工厂方法模式之规则创建源码分析

目录 1.规则创建方式 1.1.Rule注解 1.2.链式编程 1.3.表达式方式 1.4.文件脚本DSL方式 2.创建的规则类&#xff08;产品类&#xff09; 3.规则工厂类 3.1 RuleDefinition类 3.2 组合规则创建 3.3 单一规则创建 EasyRule框架的源码解析见上篇文章&#xff1a;EasyRule…

STM32:GPIO功能描述和工作方式

一、STM32控制原理概要 IO端口位的基本结构 在STM32有特定功能的内存单元&#xff0c;即"寄存器"。寄存器是程序与硬件电路通信的桥梁。寄存器按照每32位二进制0/1数据为一组。存储着芯片特定电路的相关信息。我们就是通过程序对寄存器中的数据进行修改&#xff0c;…