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

TCP网络通信——多线程

        前面分别用多进程和多路复用完成了TCP网络通信,本文就来讲讲多线程的TCP通信。首先来了解一下线程的概念:

    1、线程是进程的执行路线,它是进程内部的控制序列,或者说线程是进程的一部分(进程是一个资源单位,线程是执行单位,线程是进程的一部分,负责真正的执行)
    2、线程是轻量级的,没有自己独立的代码段、数据段、bss段、堆、环境变量、命令行参数、文件描述符、信号处理函数、当前目录信息等资源
    3、线程有自己独立的栈内存、线程ID、错误码、信号屏蔽掩码
    4、一个进程中可以包含多个线程(多个执行路线),但是至少有一个线程在活动,称为主线程
    5、ps -T -p <pid> 查看pid进程中的线程情况 或者htop命令也可以查看   
    6、线程是进程的实体,可以当做系统独立的任务调度和分配的基本单位
    7、线程有不同的状态、属性,系统提供了线程的控制接口,例如:创建、销毁、控制 
    8、进程中的所有线程同在一个虚拟地址空间中,进程中的所有资源对于线程而言都是共享的,因此当多个线程协同工作时需要解决资源竞争问题(加锁)
    9、线程的系统开销很小、任务切换快、多个线程之间不需要数据交换、因此不需要类似于XSI的通信机制,因此使用线程简单而高效
   10、线程之间有优先级的差异

在了解线程的概念之后,要想代码实现多线程TCP,还需要了解一些函数的基本用法:

1、int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
    功能:创建新线程
    thread:输出型参数,用于获取线程ID
    attr: 用于设置线程属性,一般写NULL即可
    start_routine:线程的入口函数,相当于主线程的main函数
    arg:传递给start_routine入口函数的参数
    返回值:成功返回0,失败返回错误编码

    注意:入口函数的参数、返回值要确保它的可持续性,因此不太适合使用栈内存,可以考虑堆内存、全局变量

2、int pthread_join(pthread_t thread, void **retval);
    功能:等待线程结束,并获取该线程结束时的入口函数的返回值,并释放线程资源
    thread:要等待的线程的ID
    retval:用于存储线程结束时返回值的地址,拿到返回值变量本身
    返回值:成功返回0,失败返回错误编码

3、 pthread_t pthread_self(void);
    功能:获取当前线程的线程ID    此函数在哪里调用就取哪里的线程ID

4、int pthread_equal(pthread_t t1, pthread_t t2);
    功能:比较两个线程ID是否一致
    返回值:一致返回非零值,不一致返回0
    注意:在个别操作系统下,pthread_t 是以结构实现的,大部分是以 unsigned long 呈现,为了可移植性,不能直接使用 == 比较
        pthread_t tid;  //不要初始化 提高可移植性

下面就来看一下代码实现部分:

服务端:

#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <pthread.h>  typedef struct Client 
{int cli_fd;pthread_t tid;struct sockaddr_in cli_addr;
} Client;size_t client_count = 0;void* run(void* arg)
{  //立刻保存,否则新的连接可能会覆盖上一个连接,导致操作的都是最后一个线程int cli_fd = *(int*)arg;char buf[4096];  size_t buf_size = sizeof(buf);  while (1){  int ret = recv(cli_fd, buf, buf_size, 0);  if (ret <= 0 || strcmp(buf, "quit") == 0){  printf("客户端%d退出\n", cli_fd);close(cli_fd);  return NULL;  }  printf("from %d recv: %s bits: %d tid:%lu\n", cli_fd, buf, ret,pthread_self());  strcat(buf, ":return");  send(cli_fd, buf, strlen(buf) + 1, 0);  if (ret <= 0){close(cli_fd);printf("客户端%d退出\n", cli_fd);  break;  }  }  close(cli_fd);  pthread_exit(NULL);  
}int main(int argc, const char* argv[])  
{  int sockfd = socket(AF_INET, SOCK_STREAM, 0);  if (sockfd < 0) {  perror("socket");  return -1;  }  struct sockaddr_in addr = {},cli_addr = {};  addr.sin_family = AF_INET;  addr.sin_port = htons(8866);  addr.sin_addr.s_addr = inet_addr("127.0.0.1");  socklen_t addrlen = sizeof(addr);  if (bind(sockfd, (struct sockaddr*)&addr, addrlen) < 0){  perror("bind");  return -1;  }  if (listen(sockfd, 5) < 0){  perror("listen");  return -1;  }  //准备服务客户端的结构体50个Client *client = calloc(50,sizeof(Client));size_t index = 0;while (1){  //找空闲的client(cli_fd为0,认为是空闲)while(client[index].cli_fd){//若没有空闲,则等待10s钟再尝试if(client_count>=50){sleep(10);}index = (index+1)%50;}//从上面的循环出来。则第index个client是空闲的client[index].cli_fd = accept(sockfd, (struct sockaddr*)&client[index].cli_addr, &addrlen);  if(client[index].cli_fd<0){perror("accept");continue;}pthread_create(&client[index].tid, NULL, run, (void*)(&client[index].cli_fd));client_count++;/*pthread_t tid;int cli_fd = accept(sockfd, (struct sockaddr*)&cli_addr, &addrlen);  if (cli_fd < 0){  perror("accept");continue;  }  //创建线程处理客户端请求pthread_create(&tid, NULL, run, (void*)(&cli_fd));  //usleep(1000);pthread_detach(tid);*/}  return 0;
}  

客户端:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>typedef struct sockaddr *SP;int main(int argc,const char* argv[])
{//创建socketint cli_fd=socket(AF_INET,SOCK_STREAM,0);if(cli_fd<0){perror("socket");return -1;}//准备通信地址struct sockaddr_in addr={};addr.sin_family=AF_INET;addr.sin_port=htons(8866);addr.sin_addr.s_addr=inet_addr("127.0.0.1");socklen_t addrlen=sizeof(addr);//连接服务器if(connect(cli_fd,(SP)&addr,addrlen)){perror("connect");return -1;}char buf[4096];size_t buf_size=sizeof(buf);while(1){//发送请求printf(">>>>>");scanf("%s",buf);int ret=send(cli_fd,buf,strlen(buf)+1,0);//ret=write(cli_fd,buf,strlen(buf)+1);if(ret<=0){printf("服务器正在升级,请稍后重试\n");break;}if(0==strcmp("quit",buf)){printf("通信结束\n");break;}//接收请求//int ret=read(cli_fd,buf,buf_size);ret=recv(cli_fd,buf,buf_size,0);if(ret<=0){printf("服务器正在维护,请稍候重试\n");break;}printf("read:%s bits:%d\n",buf,ret);}return 0;
}

over

相关文章:

TCP网络通信——多线程

前面分别用多进程和多路复用完成了TCP网络通信&#xff0c;本文就来讲讲多线程的TCP通信。首先来了解一下线程的概念&#xff1a; 1、线程是进程的执行路线&#xff0c;它是进程内部的控制序列&#xff0c;或者说线程是进程的一部分(进程是一个资源单位&#xff0c;线程是执行单…...

【exp报错注入】

整数范围 最大整数 exp 函数介绍 报错盲注注入 payload分析 709C-ASCII 值就等于我们下面的 7091-1 &#xff0c;C就是我们要猜的值&#xff0c;当我们猜测的值和ASCII码相等时&#xff0c;那么exp就不会出现报错&#xff0c;因为1-1还是等于709&#xff1a; 练习 id1 an…...

基于SpringBoot问卷调查系统小程序【附源码】

基于SpringBoot问卷调查系统小程序 效果如下&#xff1a; 管理员登录界面 管理员功能界面 调查人管理界面 问卷调查管理界面 问卷题目管理界面 用户登录界面 APP首页界面 公告信息界面 研究背景 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&…...

LLM - 配置 GraphRAG + Ollama 服务 构建 中文知识图谱

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142795151 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 GraphR…...

简单认识redis - 6 redis 存储速度快的原因

1基于内存存储 缓存&#xff08;内存&#xff09;读写速度很快&#xff0c;相比于磁盘存储的Mysql 省去了磁盘I/O的次数。 2.高效的数据结构 SDS动态字符串&#xff1a; 1.字符串长度处理&#xff1a;Redis获取字符串长度&#xff0c;时间复杂度为O(1)&#xff0c;而C语言中&am…...

【Qt Quick】状态:State 使用

State 是 Qt Quick 中管理界面组件状态的关键工具。它允许我们定义组件的不同状态&#xff0c;并且在用户交互或事件发生时进行状态切换&#xff0c;从而实现属性、外观和行为的动态变化。通过使用 State&#xff0c;可以避免复杂的条件逻辑&#xff0c;使代码更加简洁和可维护…...

ICE/TURN/STUN/Coturn服务器搭建

ICE 当我们想要实现在公网环境下的语音/视频通话功能时&#xff0c;就需要用到ICE交互式连接建立。ICE不是一种协议&#xff0c;整合了 STUN 和 TURN 两种协议&#xff08;用于 NAT 穿透&#xff09;的框架。 ICE的主要目标是解决NAT&#xff08;网络地址转换&#xff09;穿越…...

ctf.bugku-eval

题目来源&#xff1a;eval - Bugku CTF 访问页面&#xff0c; 代码解释 <?phpinclude "flag.php"; //包含"flag.php"文件$a $_REQUEST[hello]; //从请求参数hello中获取值并赋给变量$a。 eval( "var_dump($a);"); //…...

Extreme Compression of Large Language Models via Additive Quantization阅读

文章目录 Abstract1. Introduction2. Background & Related Work2.1. LLM量化2.2. 最近邻搜索的量化 3.AQLM:Additive Quantization for LLMs3.1. 概述3.1.0 补充**步骤说明****举例说明** 3.2. 阶段1&#xff1a;代码的波束搜索3.3. 阶段2&#xff1a;码本更新3.4. 阶段3&…...

【虚拟化】内核级虚拟化技术KVM介绍,全/半虚拟化的区别,使用libvirt搭建虚拟化平台(go/java/c++)

【虚拟化】内核级虚拟化技术KVM介绍&#xff0c;全/半虚拟化的区别&#xff0c;使用libvirt搭建虚拟化平台&#xff08;go/java/c&#xff09; 文章目录 1、虚拟化技术分类与架构&#xff08;KVM&#xff0c;Xen&#xff09;&#xff0c;全/半虚拟化的区别2、libvirt介绍3、使用…...

C++类成员变量的初始化

1、优先使用或{} 类的非静态数据成员在声明时&#xff0c;使用或{}进行初始化执行默认初始化&#xff0c;构造函数只处理一些特殊成员。 2、直接初始化 使用()进行初始化、new运算符和类构造函数的初始化列表。 3、拷贝初始化 使用进行初始化、函数传参、函数返回值。 隐式调用…...

Golang 中的强大 TUI 库 ——tview

在命令行界面下创建丰富的用户交互界面是许多开发者的需求&#xff0c;而 Golang 语言中有一个非常出色的 TUI&#xff08;文本用户界面&#xff09;库 ——tview。本文将详细介绍 tview 库&#xff0c;并与其他流行的 TUI 库进行对比&#xff0c;最后进行总结。 一、tview 库介…...

电层相关 -- 支路板与线路板

华为OTN产品系列支持 支路板、线路板分离架构 。支路/线路板和集中交叉单板配合使用&#xff0c;除了可以完成OTU单板功能外&#xff0c;还可通过集中交叉单板进行各级别ODUk颗粒业务调度&#xff0c; 实现更加灵活的电层信号调度及更高的带宽利用率。 支路板 功能 实现客户…...

leetcode 93.复原ip地址

1.题目要求&#xff1a; 2.题目代码: class Solution { public:vector<string> result;// 记录结果// startIndex: 搜索的起始位置&#xff0c;pointNum:添加逗点的数量void backtracking(string& s, int startIndex, int pointNum) {if (pointNum 3) { // 逗点数…...

AI+视频监控:EasyCVR安防平台赋能火电制造行业的视频智能管理方案

随着信息技术的飞速发展和智能制造的深入推进&#xff0c;火电制造行业作为国民经济的重要组成部分&#xff0c;正面临着智能化转型的迫切需求。为了提升生产效率、保障设备安全、优化管理流程&#xff0c;火电制造企业迫切需要引入先进的视频监控与人工智能技术。EasyCVR安防监…...

UIP协议栈 TCP Server Client通信成功案例

文章目录 这里边有相当好的 [UIP 文档资料&#xff0c;文档位置在仓库的UIP/uip doc &#xff0c;括号内是仓库地址&#xff08;https://gitee.com/free-people-in-time-and-space/net-work-learn-note.git &#xff09;TCP Server1.main循环里做的事2.以下是main循环里相关函数…...

Android Studio Koala Feature Drop 稳定版现已推出

作者 / Android Studio 产品经理 Sandhya Mohan Android Studio Koala Feature Drop (2024.1.2) 现已推出&#xff01;&#x1f428; &#x1f517; Android Studio https://developer.android.google.cn/studio 今年早些时候&#xff0c;我们宣布每个 Android Studio 动物版本…...

胤娲科技:AI评估新纪元——LightEval引领透明化与定制化浪潮

AI评估的迷雾&#xff0c;LightEval能否拨云见日&#xff1f; 想象一下&#xff0c;你是一位AI模型的开发者&#xff0c;精心打造了一个智能助手&#xff0c;却在最终评估阶段遭遇了意外的“滑铁卢”。 问题出在哪里&#xff1f;是模型本身不够聪明&#xff0c;还是评估标准太过…...

Python安装|PyCharm Professional 下载安装教程。2024最新版,亲测使用!

一、下载地址&#xff1a; 二、Python的下载及安装&#xff1a; 1、从上面网址进入Python官网 2、安装流程图&#xff1a; 双击已经下载好的python-*.*.*-amd64.exe文件&#xff0c;开始安装 最后就等它自己安装完成就好了 3、检验是否安装完成&#xff1a; windowsR快捷键…...

JavaSwitch控制流语句

在Java中&#xff0c;switch语句是一种控制流语句&#xff0c;用于根据变量的不同值执行不同的代码块。它提供了一种替代if-else语句的方式&#xff0c;使代码更简洁和易于阅读。以下是switch语句的基本语法和使用示例。 基本语法 switch (expression) {case value1:// 执行代码…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...