当前位置: 首页 > news >正文

C/S架构学习之多线程实现TCP并发服务器

  • 并发概念:
  • 并发是指两个或多个事件在同一时间间隔发生;
  • 多线程实现TCP并发服务器的实现流程:
  • 一、创建套接字(socket函数):
  • 通信域选择IPV4网络协议、套接字类型选择流式;
	int sockfd = socket(AF_INET,SOCK_STREAM,0); //通信域选择IPV4、套接字类型选择流式
  • 二、填充服务器的网络信息结构体:
  • 1.定义网络信息结构体变量;
  • 2.求出结构体变量的内存空间大小;
  • 3.结构体清零;
  • 4.使用IPV4网络协议;
  • 5.预留给在终端输入的IP地址;
  • 6.预留给在终端输入的网络字节序的端口号;
	struct sockaddr_in serveraddr; //定义网络信息结构体变量socklen_t serveraddrlen = sizeof(serveraddr);//求出结构体变量的内存空间大小memset(&serveraddr,0,serveraddrlen); //结构体清零serveraddr.sin_family = AF_INET;  //使用IPV4网络协议serveraddr.sin_addr.s_addr = inet_addr(argv[1]);  //IP地址serveraddr.sin_port = htons(atoi(argv[2]));//网络字节序的端口号
  • 三、套接字和服务器的网络信息结构体进行绑定(bind函数):
	int ret = bind(sockfd,(struct sockaddr *)&serveraddr,serveraddrlen);
  • 四、套接字设置成被动监听(listen函数):
	int ret1 = listen(sockfd, 5);
  • 五、阻塞等待客户端的连接(accept函数):
		if(-1 == (info.accept_fd = accept(sockfd,(struct sockaddr *)&(info.clientaddr),&clientaddr_len))){perror("accept error");exit(-1);}
  • 六、若有客户端连接成功,就创建线程,专门用来和该客户端通信(pthread_create函数):
		if(0 != (ret1 = pthread_create(&thread_id,NULL,message_handling,&info))){printf("pthread_create error : errno = [%d] errstr = [%s]\n",ret1,strerror(ret1));exit(EXIT_FAILURE);}
  • 七、将线程设置成分离属性,线程结束后由操作系统回收资源(pthread_detach函数):
        if(0 != (ret2 = pthread_detach(thread_id))){printf("pthread_create error : errno = [%d] errstr = [%s]\n",ret2,strerror(ret2));exit(EXIT_FAILURE);}
  • 八、创建线程处理函数用来接收来自客户端的数据(recv函数)和给客户端发送应答消息(send函数):
	//线程处理函数void *message_handling(void *arg);int nbytes = recv(acceptfd,buf,sizeof(buf),0);printf("客户端发来数据[%s]\n",buf);strcat(buf,"----k"); //组装应答消息int ret2 = send(acceptfd,buf,sizeof(buf),0);
  • 九、退出线程(pthread_exit函数)和关闭套接字(close函数):
	close(info.accept_fd);pthread_exit(NULL);
  • 综合应用实例代码如下所示:
//多线程实现TCP并发服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>typedef struct INFO
{int accept_fd;struct sockaddr_in clientaddr;}info_t;//线程处理函数
void *message_handling(void *arg);int main(int argc, char const *argv[])
{//入参合理性检查if(3 != argc){printf("Usage : %s <IP> <PORT>\n",argv[0]);exit(-1);}//创建套接字int sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){perror("socket error");exit(-1);}//填充服务器网络信息结构体struct sockaddr_in serveraddr;socklen_t serveraddr_len = sizeof(serveraddr);memset(&serveraddr,0,serveraddr_len);serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));//将套接字与服务器网络信息结构体绑定if(-1 == bind(sockfd,(struct sockaddr *)&serveraddr,serveraddr_len)){perror("bind error");exit(-1);}//将套接字设置成被监听状态if(-1 == listen(sockfd,5)){perror("listen error");exit(-1);}info_t info;pthread_t thread_id;int ret1 = 0;int ret2 = 0;socklen_t clientaddr_len = sizeof(info.clientaddr);while(true){//等待客户端连接if(-1 == (info.accept_fd = accept(sockfd,(struct sockaddr *)&(info.clientaddr),&clientaddr_len))){perror("accept error");exit(-1);}//若有客户端连接成功,就创建线程,专门用来和该客户端通信if(0 != (ret1 = pthread_create(&thread_id,NULL,message_handling,&info))){printf("pthread_create error : errno = [%d] errstr = [%s]\n",ret1,strerror(ret1));exit(EXIT_FAILURE);}//将线程设置成分离属性,线程结束后由操作系统回收资源if(0 != (ret2 = pthread_detach(thread_id))){printf("pthread_create error : errno = [%d] errstr = [%s]\n",ret2,strerror(ret2));exit(EXIT_FAILURE);}}close(sockfd);return 0;
}void *message_handling(void *arg)
{info_t info = *(info_t *)arg;printf("客户端[%s : %d]连接到服务器\n",inet_ntoa(info.clientaddr.sin_addr),ntohs(info.clientaddr.sin_port));//接收客户端数据,并作出应答int nbytes = 0;char buf[128] = {0};while(true){memset(buf,0,sizeof(buf));//接收消息if(-1 == (nbytes = recv(info.accept_fd,buf,sizeof(buf),0))){perror("recv error");break;}else if(0 == nbytes){printf("客户端[%s : %d]断开了连接\n",inet_ntoa(info.clientaddr.sin_addr),ntohs(info.clientaddr.sin_port));break;}if(!strcmp(buf,"quit")){printf("客户端[%s : %d]退出了\n",inet_ntoa(info.clientaddr.sin_addr),ntohs(info.clientaddr.sin_port));break;}printf("客户端[%s : %d]发来消息[%s]\n",inet_ntoa(info.clientaddr.sin_addr),ntohs(info.clientaddr.sin_port),buf);//组装应答strcat(buf,"------k");//发送应答if(-1 == send(info.accept_fd,buf,sizeof(buf),0)){perror("send error");break;}}close(info.accept_fd);pthread_exit(NULL);}
  • 本示例代码,仅供参考;

相关文章:

C/S架构学习之多线程实现TCP并发服务器

并发概念&#xff1a;并发是指两个或多个事件在同一时间间隔发生&#xff1b;多线程实现TCP并发服务器的实现流程&#xff1a;一、创建套接字&#xff08;socket函数&#xff09;&#xff1a;通信域选择IPV4网络协议、套接字类型选择流式&#xff1b; int sockfd socket(AF_IN…...

iPhone手机记笔记工具选择用哪个

iPhone手机大家应该都比较熟悉&#xff0c;其使用性能是比较流畅的&#xff0c;在iPhone手机上记录笔记可以帮助大家快速地进行总结工作、记录工作内容等&#xff0c;在iPhone手机上记笔记工具选择用哪个呢&#xff1f; 可以在iPhone手机上使用的笔记工具是比较多的&#xff0…...

MyBatis动态SQL(if、choose、when和otherwise)标签

动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中&#xff0c;开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。例如&#xff0c;拼接时要确保添加了必要的空格&#xff0c;还要注意去掉列表最后一个列名的逗号。而动态…...

idea将jar包deploy到本地仓库

1、pom.xml文件引入配置&#xff0c;如下参考&#xff1a; <distributionManagement><snapshotRepository><id>maven-snapshots</id><url>http://nexus1.coralglobal.cn/repository/maven-snapshots/</url></snapshotRepository><…...

麻省理工学院与Meta AI共同开发StreamingLLM框架,实现语言模型无限处理长度

&#x1f989; AI新闻 &#x1f680; 麻省理工学院与Meta AI共同开发StreamingLLM框架&#xff0c;实现语言模型无限处理长度 摘要&#xff1a;麻省理工学院与Meta AI的研究人员联合研发了一款名为StreamingLLM的框架&#xff0c;解决了大语言模型在RAM与泛化问题上的挑战&am…...

记录 K8S 挂了的解决经过

背景&#xff1a;早上到公司&#xff0c;有同事反馈部署K8S在集群上的 Redis 和 禅道 都不可用 排查循序&#xff1a; 登录 kubesphere 的 web 界面 &#xff08;界面打开失败&#xff09;ssh 登录主服务器 &#xff08;正常&#xff09;在主服务器上运行 kubectl get node 命…...

Flink---11、状态管理(按键分区状态(值状态、列表状态、Map状态、归约状态、聚合状态)算子状态(列表状态、广播状态))

星光下的赶路人star的个人主页 这世上唯一扛得住岁月摧残的就是才华 文章目录 1、状态管理1.1 Flink中的状态1.1.1 概述1.1.2 状态的分类 1.2 按键分区状态&#xff08;Keyed State&#xff09;1.2.1 值状态&#xff08;ValueState&#xff09;1.2.2 列表状态&#xff08;ListS…...

Vue3中使用tinymce全功能演示,包括开源功能

效果图&#xff1a; 1、下载插件: npm i tinymce npm i tinymce/tinymce-vue 2、在node_modules文件夹中找到tinymce下的skins复制到项目public文件夹中 &#xff08;可以先创建一个tinymce文件夹&#xff09;&#xff1a; 3、在tinymce官网中下载中文包&#xff0c;并放在刚…...

There was an error committing your changes: File could not be edited

使用github完成commit changes时报的一个错误&#xff0c;最终原因是没有填写Extended description...

10月9日,每日信息差

今天是2023年10月9日&#xff0c;以下是为您准备的14条信息差 第一、首只与规模挂钩型浮动费率基金即将面市。作为公募基金费率改革大背景下的首批浮动费率产品&#xff0c;华夏信兴回报混合是市场上首只管理费与管理规模挂钩的基金 第二、江北新区成立百亿产业发展母基金&am…...

【软考设计师】S01 数据结构 E01 线性结构 P01 线性表

线性表 前言——线性结构线性表线性表的定义线性表的特点线性表的存储结构顺序存储链式存储单链表双向链表循环链表静态链表 前言——线性结构 线性结构是一种基本的数据结构&#xff0c;主要用于对客观世界中具有单一前驱和后继的数据关系进行描述。线性结构的特点是数据元素…...

nginx配置https 访问

nginx 解压目录有configure文件 [rootoracledb10 ~]# which nginx1、检查nginx是否包含http_ssl_module 模块 如果出现 --with-http_ssl_module 就是已经安装了[rootoracledb10 sbin]# pwd /usr/local/nginx/sbin [rootoracledb10 sbin]# nginx -V nginx version: nginx/1.23…...

希亦CG声波清洗机:眼镜党福利,家庭必备清洗机

对于眼镜党来说最大的烦恼就是每天的佩戴和清洗&#xff0c;清洗是至关重要的&#xff0c;错误的清洗很容易引起镜片损坏&#xff0c;个人一直使用眼镜布清洗&#xff0c;除了费时费力之外清洁度也无法保证。希亦CG声波清洗机正是为了解决这一难题应运而生&#xff0c;可以彻底…...

2023年10月12日历史上的今天大事件早读

公元前539年10月12日波斯国王大流士的军队攻克巴比伦 1492年10月12日西班牙独立日 1492年10月12日哥伦布“发现新大陆” 1773年10月12日法国天文学家梅西叶首次发现具有螺旋结构的星系 1885年10月12日清政府改台湾府为行省 命刘铭传为台湾巡抚 1929年10月12日苏军向张学良…...

uCOSIII实时操作系统 五 任务API(时间片轮转API调度)

时间片轮转调度 时间片轮转法&#xff1a;主要用于分时系统中的进程调度。为了实现轮转调度&#xff0c;系统把所有就绪进程按照先入先出的原则排成一个队列的队首进程&#xff0c;让CPU上运行一个时间片的时间。时间片是一个小小的时间单位,通常为5~10ms数量级。当进程用完分…...

微信小程序项目如何用Hbuild启动,先让对方在微信开发平台将你的微信号添加成开发成员。

微信小程序项目如何用Hbuild启动&#xff0c;先让对方在微信开发平台将你的微信号添加成开发成员。然后在Hbuild官网下载&#xff0c;下载好后运行&#xff0c;点击文件导入项目&#xff0c;然后点击运行&#xff0c;模拟微信小程序&#xff0c;选择微信开发工具的地址&#xf…...

应对广告虚假流量,app广告变现该如何风控?

移动广告市场中的虚假流量一直是困扰各移动应用厂商的难题&#xff0c;广告作为app商业化变现最为直接快捷的途径&#xff0c;也引申出了流量作弊与反作弊的纷争。 根据《2021中国异常流量报告》&#xff0c;2021年中国品牌广告市场因异常流量造成的损失约为326亿人民币&#…...

【算法-动态规划】贝尔曼福特算法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…...

【23-24 秋学期】NNDL 作业3

过程推导 - 了解BP原理数值计算 - 手动计算&#xff0c;掌握细节代码实现 - numpy手推 pytorch自动 对比【numpy】和【pytorch】程序&#xff0c;总结并陈述。激活函数Sigmoid用PyTorch自带函数torch.sigmoid()&#xff0c;观察、总结并陈述。激活函数Sigmoid改变为Relu&#…...

v-on/@ 事件处理指令修饰符-stop、prevent、once

v-on/事件修饰符&#xff1a; 一、.stop 阻止单机事件继续传播 event.stopProgagetion() eg: <h3>事件修饰符</h3> <div click"todo"> <div click.stop"doThis"> 单机事件会继续传递 </div> </div> 点击 单机事…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

解析“道作为序位生成器”的核心原理

解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制&#xff0c;重点解析"道作为序位生成器"的核心原理与实现框架&#xff1a; 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...

CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14

什么是 Pattern Matching&#xff08;模式匹配&#xff09; ❝ 模式匹配就是一种“描述式”的写法&#xff0c;不需要你手动判断、提取数据&#xff0c;而是直接描述你希望的数据结构是什么样子&#xff0c;系统自动判断并提取。❞ 你给的定义拆解&#xff1a; ✴ Instead of …...