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

Linux 多线程并发Socket服务端的实现( 11 ) -【Linux通信架构系列 】

系列文章目录

C++技能系列
Linux通信架构系列
C++高性能优化编程系列
深入理解软件架构设计系列
高级C++并发线程编程
设计模式系列

期待你的关注哦!!!
在这里插入图片描述

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

Linux 多线程并发Socket服务端的实现

  • 系列文章目录
  • 一、Linux线程的介绍
  • 二、多线程并发服务端的实现

一、Linux线程的介绍

  • (1)头文件
    #include < pthread.h >

  • (2)创建线函数
    int pthread_create( pthread_t * restrict thread, const pthread_attr_t * restrict attr, void* (* start_routine)(void *), void * restrict arg );
    成功时返回0,失败时返回其他值。
    thread : 保存新创建线程ID的变量地址。区分不同线程;
    attr : 用于传递线程属性的参数,传递NULL时,创建默认属性的线程;
    start_routine : 相当于线程main函数的、在单独执行流中执行的函数的地址值(函数指针);
    arg : 通过第三个函数传递调用函数时包含传递参数信息的变量地址值。
    调用pthread_join函数 - 与之聚合(等待线程终止)
    int pthread_join(pthread_t thread, void ** status);
    成功时返回0,失败时返回其他值。
    – thread : 该参数值ID的线程终止后才会从该函数返回;
    – status : 保存线程的main函数返回值的指针变量地址值。
    调用pthread_detach函数 - 与之分离
    int pthread_detach(pthread_t thread);
    成功时返回0,失败时返回其他值。
    – thread 终止的同时需要销毁的线程ID。

  • (3)互斥量
    int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutex * attr);
    int pthread_mutex_destroy(pthread_mutex_t * mutex);
    成功时返回0,失败时返回其他值。
    – mutex 创建互斥量时传递保存互斥量的变量地址值,销毁时传递需要销毁的互斥量的地址值;
    – attr 传递即将创建的互斥量属性,没有特别需要指定的属性时传递NULL。
    int pthread_mutex_lock(pthred_mutex_t * mutex);
    int pthread_mutex_unlock(pthread_mutex_t * mutex);
    成功时返回0,失败时返回其他值。
    互斥量锁。

  • (4)信号量
    #include< semaphore.h >
    int sem_init (sem_t * sem, int pshared, unsigned int value);
    int sem_destroy (sem_t * sem);
    成功时返回0,失败时返回其他值。
    – sem :创建信号时传递保存信号量的变量的地址值,销毁时传递需要销毁的信号量变量地址值;
    – pshared :传递其他值时,创建可由多个进程共享的信号量;传递0时,创建只允许1个进程内部使用的信号量;
    – value :指定新创建信号量的初始值。
    int sem_post (sem_t * sem);
    int sem_wait (sem_t * sem);
    成功时返回0,失败时返回其他值。
    – sem :传递保存信号量读取值的变量地址值,传递给sem_post时信号量增1,传递给sem_wait时信号量减1,信号值不能小于0,因此,在信号量为0的时候调用sem_wait函数时,线程进入阻塞状态。

二、多线程并发服务端的实现

如下介绍是多个客户端之间可以交换信息的简单的聊天程序(不是严格的商业代码)。

chart_server.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<fcntl.h>
#include<errno.h>
#include<pthread.h>
#define BUF_SIZE 100
#define MAX_CLNT 256void * handle_clnt(void * arg);
void send_msg(char * msg, int len);
void error_handling(char * msg);
int clnt_cnt = 0;
int clnt_socks[MAX_CLNT];
pthread_mutex_t mutex;int main(int argc, char *argv[])
{//用来管理接入的客户端套接字的变量和数组。访问这两个变量的代码将构成临界区int serv_sock, clnt_sock; struct sockaddr_in serv_adr, clnt_adr;int clnt_adr_sz;pthread_t t_id;if(argc != 2){printf("Usage : %s <port> \n", argv[0]);exit(1);}pthread_mutex_init(&mutex, NULL);serv_sock = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_adr, 0, sizeof(serv_adr));serv_adr.sin_family = AF_INET;serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);serv_adr.sin_port = htons(atoi(argv[1]));if(bind(serv_sock, (struct sockaddr *) &serv_adr, sizeof(serv_adr)) == -1)error_handling("bind() error");if(listen(serv_sock, 5) == -1)error_handling("listen() error");while(1){clnt_adr_sz = sizeof(clnt_adr);clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &clnt_adr_sz);pthread_mutex_lock(&mutex);//每当有新的连接时,将相关信息写入变量clnt_cnt和clnt_socksclnt_socks[clnt_cnt++] = clnt_sock;pthread_mutex_unlock(&mutex);//创建线程向新连入的客户端提供服务pthread_create(&t_id, NULL, handle_clnt, (void*)&clnt_sock);//调用pthread_detach函数从内存中完全销毁已终止的线程pthread_detach(t_id);printf("Connected client IP: %s \n", inet_ntoa(clnt_adr.sin_addr));}close(serv_sock);return 0;
}void * handle_clnt(void * arg)
{int clnt_sock = *((int*)arg);int str_len = 0, i;char msg[BUF_SIZE];while((str_len = read(clnt_sock, msg, sizeof(msg))) != 0)send_msg(msg, str_len);pthread_mutex_lock(&mutex);for(i = 0; i < clnt_cnt; i++) //remove disconnected client{if(clnt_sock == clnt_socks[i]){while(i++ < clnt_cnt - 1)clnt_socks[i] = clnt_socks[i + 1];break;}}clnt_cnt--;pthread_mutex_unlock(&mutex);close(clnt_sock);return NULL;
}//该函数负责向所有客户端发送消息
void send_msg(char *msg, int len) // send to all
{int i;pthread_mutex_lock(&mutex);for(i = 0; i < clnt_cnt; i++)write(clnt_socks[i], msg, len);pthread_mutex_unlock(&mutex);
}void error_handling(char *msg)
{fputs(msg, stderr);fputc('\n', stderr);exit(1);
}

chat_clnt.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<fcntl.h>
#include<errno.h>
#include<pthread.h>
#define BUF_SIZE 100
#define NAME_SIZE 20void * send_msg(void *arg);
void * recv_msg(void *arg);
void error_handling(char *msg);char name[NAME_SIZE] = "[DEFAULT]";
char msg[BUF_SIZE];int main(int argc, char *argv[])
{int sock;struct sockaddr_in serv_addr;pthread_t snd_thread, rcv_thread;void *thread_return;if(argc != 4){printf("Usage : %s <IP> <port> <name> \n", argv[0]);exit(1);}sprintf(name, "[%s]", argv[3]);sock = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port = htons(atoi(argv[2]));if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)error_handling("connect() error");pthread_create(&snd_thread, NULL, send_msg, (void *)&sock);pthread_create(&rcv_thread, NULL, recv_msg, (void *)&sock);pthread_join(snd_thread, &thread_return);pthread_join(rcv_thread, &thread_return);close(sock);return 0;
}void *send_msg(void *arg) //send thread main
{int sock = *((int *)arg);char name_msg[NAME_SIZE + BUF_SIZE];while(1){fgets(msg, BUF_SIZE, stdin);if(!strcmp(msg, "q\n") || !strcmp(msg, "Q\n")){close(sock);exit(0);}sprintf(name_msg, "%s %s", name, msg);write(sock, name_msg, strlen(name_msg));}return NULL;
}void *recv_msg(void * arg) //read thread main
{int sock = *((int *) arg);char name_msg[NAME_SIZE + BUF_SIZE];int str_len;while(1){str_len = read(sock, name_msg, NAME_SIZE + BUF_SIZE - 1);if(str_len == -1)return (void *) - 1;name_msg[str_len] = 0;fputs(name_msg, stdout);}return NULL;
}void error_handling(char *msg)
{fputs(msg, stderr);fputc('\n', stderr);exit(1);
}

运行结果如下:
在这里插入图片描述

图1_1 聊天室运行结果

相关文章:

Linux 多线程并发Socket服务端的实现( 11 ) -【Linux通信架构系列 】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everythi…...

2.7. Java 泛型了解么?什么是类型擦除?介绍一下常用的通配符?

Java 泛型&#xff08;generics&#xff09;是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制&#xff0c;该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型&#xff0c;也就是说所操作的数据类型被指定为一个参数。 Java 的泛型是伪泛型&am…...

单例模式与构造器模式

单例模式 1、是什么 单例模式&#xff08;Singleton Pattern&#xff09;&#xff1a;创建型模式&#xff0c;提供了一种创建对象的最佳方式&#xff0c;这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有单个对象被创建 在应用程序运…...

SQL力扣练习(七)

1.行程和用户(262) 表&#xff1a;Trips ----------------------- | Column Name | Type | ----------------------- | id | int | | client_id | int | | driver_id | int | | city_id | int | | status | enum | | reques…...

C语言假期作业 DAY 05

题目 一、选择题 1、如下程序的功能是&#xff08; &#xff09; #include <stdio.h> int main() { char ch[80] "123abcdEFG*&"; int j; puts(ch); for(j 0; ch[j] ! \0; j) if(ch[j] > A && ch[j] < Z) ch[j] ch[j] e - E; puts(ch)…...

php-golang-rpc使用roadrunner-server/goridge/v3/pkg/rpc和php的spiral/goridge3.2实践

golang代码&#xff1a; go get github.com/roadrunner-server/goridge/v3 package main import ( "fmt" "net" "net/rpc" goridgeRpc "github.com/roadrunner-server/goridge/v3/pkg/rpc" ) type App struct{} func (s *App) Hi(na…...

API常用签名验证方法(PHP实现)

使用场景 现在越来越多的项目使用的前后端分离的模式进行开发&#xff0c;后端开发人员使用API接口传递数据给到前端开发进行处理展示&#xff0c;在一些比较重要的修改数据接口&#xff0c;涉及金钱&#xff0c;用户信息等修改的接口如果不做防护验证&#xff0c;经常容易被人…...

kotlin高阶函数

kotlin高阶函数 函数式API:一个函数的入参数为Lambda表达式的函数就是函数式api 例子: public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {return filterTo(ArrayList<T>(), predicate) }上面这段函数: 首先这个函…...

kotlin list集合树

kotlin list集合树 记录一下 data class AreaSchemaManageDto(var id: Long? null,var pid: Long? null,var label: String? null,var children: MutableList<AreaSchemaManageDto>? null ) : Serializable { }逻辑 fun getAll(): List<AreaSchemaManageDto&g…...

基于Autoencoder自编码的64QAM星座图整形调制解调通信系统性能matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1星座图整形 4.2自编码器 4.3基于Autoencoder的星座图整形调制解调模型 4.4 实现过程 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .…...

【Spring】Spring 总览

一、简单介绍一下 Spring Spring是一个全面的、企业应用开发的一站式解决方案&#xff0c;贯穿表现层、业务层、持久层&#xff0c;可以轻松和其他框架整合&#xff0c;具有轻量级、控制反转、面向切面、容器等特征。 轻量级 &#xff1a; 空间开销和时间开销都很轻量 控制反…...

微软、OpenAI用上“数据永动机” 合成数据是晨曦还是暮光?

微软、OpenAI、Cohere等公司已经开始测试使用合成数据来训练AI模型。Cohere首席执行官Aiden Gomez表示&#xff0c;合成数据可以适用于很多训练场景&#xff0c;只是目前尚未全面推广。 已有的&#xff08;通用&#xff09;数据资源似乎接近效能极限&#xff0c;开发人员认为&a…...

简单认识Redis 数据库的高可用

文章目录 一、Redis 高可用&#xff1a;1.简介&#xff1a;2、在Redis中实现高可用的技术 二、Redis持久化&#xff1a;1.持久化的功能&#xff1a;2.Redis 提供两种方式进行持久化&#xff1a; 三、RDB 持久化&#xff1a;1.简介&#xff1a;2.触发条件&#xff1a;4.启动时加…...

超级实用!,掌握这9个鲜为人知的CSS属性

微信搜索 【大迁世界】, 我会第一时间和你分享前端行业趋势&#xff0c;学习途径等等。 本文 GitHub https://github.com/qq449245884/xiaozhi 已收录&#xff0c;有一线大厂面试完整考点、资料以及我的系列文章。 快来免费体验ChatGpt plus版本的&#xff0c;我们出的钱 体验地…...

深圳国际新能源及智能网联汽车全产业博览会今年10月举办

7月25日&#xff0c;深圳市工业和信息化局与励展博览集团共同在深圳举办Automotive World China 2023深圳国际新能源及智能网联汽车全产业博览会&#xff08;简称“AWC 2023”&#xff09;全球推介启动大会&#xff0c;该博览会将于2023年10月11日-13日在深圳国际会展中心盛大举…...

【具有非线性反馈的LTI系统识别】针对反馈非线性的LTI系统,提供非线性辨识方案(SimulinkMatlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码、Simulink仿真实现 &#x1f4a5;1 概述 本文为具有反馈非线性的LTI系统提供了一种非线性识别方案&#xff0c;这取决于输入和LTI系统输出。对于MEMS来说尤其如此&#…...

Stable diffusion 和 Midjourney 怎么选?

通过这段时间的摸索&#xff0c;我将和你探讨&#xff0c;对普通人来说&#xff0c;Stable diffusion 和 Midjourney 怎么选&#xff1f;最重要的是&#xff0c;学好影视后期制作对 AI 绘画创作有哪些帮助&#xff1f;反过来&#xff0c;AI 绘画对影视后期又有哪些帮助&#xf…...

c++网络编程

网络编程模型 c/s 模型&#xff1a;客户端服务器模型b/s 模型&#xff1a;浏览器服务器模型1.tcp网络流程 服务器流程&#xff1a; 1.创建套接字2.完善服务器网络信息结构体3.绑定服务器网络信息结构体4.让服务器处于监听状态5.accept阻塞等待客户端连接信号6.收发数据7.关闭套…...

【沁恒蓝牙mesh】数据收发接口与应用层模型传递

本文主要描述了沁恒蓝牙mesh SDK的蓝牙数据收发接口&#xff0c;以及应用层的回调函数解析以及模型传递 这里写目录标题 1. 数据收发接口1.1【发送数据】1.2 【数据接收】 2. 应用层模型分析 1. 数据收发接口 1.1【发送数据】 /*&#xff08;1&#xff09;接口1 */ /*接口一&…...

Java类关系之代理(代理模式)

在Java中&#xff0c;如果一个类需要使用另一个类的方法&#xff0c;我们可以使用继承的方式实现&#xff0c;那么问题来了&#xff0c;如果这个类恰恰在逻辑关系上不能使用继承怎么办呢&#xff1f;比如说&#xff0c;飞机和控制台这两个类&#xff0c;控制台的方法有上下左右…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;Floyd 快慢指针法&#xff08;…...

XXE漏洞知识

目录 1.XXE简介与危害 XML概念 XML与HTML的区别 1.pom.xml 主要作用 2.web.xml 3.mybatis 2.XXE概念与危害 案例&#xff1a;文件读取&#xff08;需要Apache >5.4版本&#xff09; 案例&#xff1a;内网探测&#xff08;鸡肋&#xff09; 案例&#xff1a;执行命…...

C++参数传递 a与a的区别

在 C 中&#xff0c;&a&#xff08;引用&#xff09;和 a&#xff08;值传递&#xff09; 的关键区别在于 参数如何传递给函数&#xff0c;以及由此引发的 性能、语义和安全问题。 最核心的在于你想不想传入的参数被改变&#xff0c;如果想&#xff0c;就用参数传递&#…...

[学习笔记]使用git rebase做分支差异化同步

在一个.NET 项目中&#xff0c;使用了Volo.Abp库&#xff0c;但出于某种原因&#xff0c;需要源码调试&#xff0c;因此&#xff0c;使用源码方式集成的项目做了一个分支archive-abp-source 其中引用方式变更操作的提交为&#xff1a;7de53907 后续&#xff0c;在master分支中…...