Linux C/C++ 多线程TCP/UDP服务器 (监控系统状态)
Linux环境中实现并发TCP/IP服务器。多线程在解决方案中提供了并发性。由于并发性,它允许多个客户端同时连接到服务器并与服务器交互。
Linux多线程编程概述
许多应用程序同时处理多项杂务。服务器应用程序处理并发客户端;交互式应用程序通常在处理后台计算时处理用户输入;计算密集型应用程序利用多个处理器的功能。共同的主题是使用多个控制线程来提供处理并发活动的上下文,无论是在一个处理器上多路复用、在多个处理器上并行执行,还是利用具有“超线程技术”的处理器以及AMD和Intel的新双核处理器的设施。
协调这些线程的执行涉及同步对共享数据结构的访问,确保程序行为良好且具有确定性,而不管其组件线程的相对执行速度如何。多线程程序和单线程程序一样,必须处理异常和与外界的交互。尽管在这样的程序中可能有许多并发活动,但程序作为一个整体应该对这样的外部输入做出清晰的响应。
线程的实现方式有很多种,包括用户级库、内核和各种组合。大多数Linux实现目前将每个线程视为使用克隆系统调用创建的单独进程(尽管每个线程都与其队列共享其地址空间)。
C/C++ 多线程并发服务器知识点
- 多线程并发服务器思路
1. socket(),创建监听套接字
2. bind(),绑定监听套接字
3. setsockopt(),设置端口复用
4. listen(),监听状态,用来被动接受来自其他主动套接字的连接请求,并设置监听上限
5. pthread_attr_init()、pthread_attr_setdetachstate()、pthread_create(),在创建时指定属性
6. pthread_rwlock_wrlock()、pthread_rwlock_unlock(),并发程序引起的共享内存问题
...
Linux C/C++ 多线程TCP/UDP服务器 (监控系统状态)
目的:使用TCP/IP实现多线程客户端服务器。它允许多个客户端同时连接到服务器并与服务器交互。处理多线程TCP/UDP服务器监控系统状态:监控CPU负载、RAM使用情况、磁盘空间使用情况和可用网络接口。
服务器:
启动服务器并接受来自客户端的连接。在接受客户机连接后,它分派一个线程与客户机交互。
...
int main(int argc, char *argv[])
{if (argc != 4){printf ("Usage: %s <TCP/UDP> <port> <max_connections>\n", argv[0]);return 0;}if (strncmp ("TCP", argv[1], 3) == 0){printf ("Using TCP");protocol = TCP;}else if (strncmp ("UDP", argv[1], 3) == 0){printf ("Using UDP");protocol = UDP;}else{printf ("Unknown protocol: %s\n", argv[1]);printf ("Usage: %s <TCP/UDP> <port> <max_connections>\n", argv[0]);return 0;}const int port = atoi (argv[2]);if (!port){printf ("Wrong port number: %s\n", argv[2]);printf ("Usage: %s <TCP/UDP> <port> <max_connections>\n", argv[0]);return 0;}const int max_connections = atoi (argv[3]);if (!max_connections){printf ("Wrong max_connections number: %s\n", argv[3]);printf ("Usage: %s <TCP/UDP> <port> <max_connections>\n", argv[0]);return 0;}printf (" on port %i with no more than %i clients\n", port, max_connections);/* Assign signal handlers to signals. */if (signal (SIGPIPE, SIG_IGN) == SIG_ERR){perror ("signal");exit (EXIT_FAILURE);}if (signal (SIGTERM, signal_handler) == SIG_ERR){perror ("signal");exit (EXIT_FAILURE);}if (signal (SIGINT, signal_handler) == SIG_ERR){perror ("signal");exit (EXIT_FAILURE);}pthread_attr_t pthread_attr;pthread_arg_t *pthread_arg;pthread_t pthread;//为属性对象分配了动态内存空间if (pthread_attr_init (&pthread_attr) != 0){perror("pthread_attr_init");exit (EXIT_FAILURE);}//设置线程分离状态if (pthread_attr_setdetachstate (&pthread_attr, PTHREAD_CREATE_DETACHED) != 0){perror("pthread_attr_setdetachstate");exit (EXIT_FAILURE);}// 开始观测//指定已初始化的读写锁pthread_rwlock_init (&rwlock, NULL);if (pthread_create (&pthread, &pthread_attr, pthread_sysinfo, NULL) != 0){perror("pthread_create");exit (EXIT_FAILURE);}struct addrinfo hints;struct addrinfo *result, *rp;int socket_fd;memset(&hints, 0, sizeof(struct addrinfo));hints.ai_family = AF_UNSPEC;hints.ai_socktype = (protocol == TCP) ? SOCK_STREAM : SOCK_DGRAM;hints.ai_flags = AI_PASSIVE;hints.ai_protocol = 0;hints.ai_canonname = NULL;hints.ai_addr = NULL;hints.ai_next = NULL;int s = getaddrinfo(NULL, argv[2], &hints, &result);if (s != 0){fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));exit(EXIT_FAILURE);}for (rp = result; rp != NULL; rp = rp->ai_next){socket_fd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);if (socket_fd == -1)continue;if (bind(socket_fd, rp->ai_addr, rp->ai_addrlen) == 0)break; /* Success */close (socket_fd);}if (rp == NULL) /* No address succeeded */{fprintf(stderr, "Could not bind\n");exit (EXIT_FAILURE);}freeaddrinfo (result);if (protocol == UDP){struct timeval timeout = {5, 0};//设置端口复用setsockopt (socket_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(struct timeval));for (;; udp_reply (socket_fd));}if (listen (socket_fd, BACKLOG) == -1){perror ("listen");exit (EXIT_FAILURE);}while (protocol == TCP){pthread_arg = (pthread_arg_t *) malloc (sizeof *pthread_arg);if (!pthread_arg){perror ("malloc");exit (EXIT_FAILURE);}socklen_t client_address_len = sizeof pthread_arg->client_address;int tcp_socket_fd = accept (socket_fd, (struct sockaddr *)&pthread_arg->client_address,&client_address_len);connections++;if (tcp_socket_fd == -1){perror ("accept");free (pthread_arg);exit (EXIT_FAILURE);}else if (connections > max_connections){close (tcp_socket_fd);connections--;free (pthread_arg);continue;}printf ("New TCP connection accepted: now there are %i clients\n", connections);pthread_arg->new_socket_fd = tcp_socket_fd;if (pthread_create (&pthread, &pthread_attr, pthread_routine_tcp, (void *)pthread_arg) != 0){perror("pthread_create");free (pthread_arg);exit (EXIT_FAILURE);}}return 0;
}
...
void *pthread_sysinfo ()
{char *s = system_state_report ();strcpy (system_state, s);free (s);for (;;){if (connections > 0 || protocol == UDP){s = system_state_report ();pthread_rwlock_wrlock (&rwlock);strcpy (system_state, s);pthread_rwlock_unlock (&rwlock);free (s);}}return NULL;
}void signal_handler (int signal_number)
{/* Exit cleanup code here. */// close (socket_fd);exit (EXIT_SUCCESS);
}
...
char *system_state_report ()
{json_t *root = json_loads (BLANC_JSON_REPORT, 0, NULL);cpu_usage (json_object_get(root, "CPU, %"));ram_usage (json_object_get(root, "RAM"));storage_usage (json_object_get(root, "Storage"));net_usage (json_object_get(root, "Network"));time_stamp (root);char *s = json_dumps (root, 0);json_decref (root);return s;
}int cpu_usage (json_t *cpu_state)
{char buff[TXT_BUFFER_SIZE][TXT_BUFFER_SIZE];int ncpu = get_nprocs ();FILE* fp = fopen(STAT_PATH,"r");for (int i = 0; i < ncpu + 1; i++){fgets(buff[i], TXT_BUFFER_SIZE, fp);}fclose(fp);sleep(TIME_LAG);fp = fopen(STAT_PATH,"r");for (int i = 0; i < ncpu + 1; i++){fgets(buff[i + ncpu + 1], TXT_BUFFER_SIZE, fp);}fclose(fp);for (int i = 0; i < ncpu + 1; i++){long long sum = 0, lastSum = 0;long long idle, lastIdle;char* token = strtok(buff[i], " ");for (int col = 0; token != NULL;){token = strtok (NULL, " ");if (token != NULL){lastSum += atoll (token);if (col == 3)lastIdle = atoll (token);col++;}}
...int cpu_usage_pct = (1000 *((sum - lastSum) - (idle - lastIdle)) / (sum - lastSum) + 5) / 10;json_t *json_cpu_pct;json_cpu_pct = json_integer(cpu_usage_pct);json_array_append (cpu_state, json_cpu_pct);json_decref (json_cpu_pct);}return 0;
}...
客户端:
与服务器交互。通常,会使用write将消息中的消息发送到服务器,并使用read从服务器接收消息并将其存储在消息中。
...
int main(int argc, char *argv[])
{
...if (argc < 4){fprintf (stderr, "Usage: %s <host> <port> <update_time (seconds)>\n", argv[0]);exit(EXIT_FAILURE);}const int time_lag = atoi (argv[3]);if (!time_lag){fprintf( stderr, "Impossible time lag: %s\n", argv[3]);exit(EXIT_FAILURE);}memset(&hints, 0, sizeof(struct addrinfo));hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */hints.ai_socktype = 0; /* Any type: TCP/UDP */hints.ai_flags = 0;hints.ai_protocol = 0; /* Any protocol */s = getaddrinfo(argv[1], argv[2], &hints, &result);if (s != 0){fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));exit(EXIT_FAILURE);}for (rp = result; rp != NULL; rp = rp->ai_next){sfd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);if (sfd == -1)continue;if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)break;close(sfd);}if (rp == NULL){fprintf (stderr, "Could not connect to server %s at port: %s\n", argv[1], argv[2]);exit(EXIT_FAILURE);}freeaddrinfo(result);// Server interaction.for (;; sleep (time_lag)){char msg[BUF_SIZE];char s[BUF_SIZE];bzero (msg, BUF_SIZE);write (sfd, "report", 6);int server_response = read (sfd, msg, BUF_SIZE);if (server_response <= 0){printf ("Connection is closed by server\n");break;}status (msg, s);printf ("%s\n", s);}...
}int status (const char *src, char *report)
{
...int ncpu = json_array_size (cpu_status);int tot_cpu_usage = json_integer_value (tot_cpu_load);char buff[BUF_SIZE];sprintf (report, "Total usage of %2i CPUs: %3i%%, ", ncpu - 1, tot_cpu_usage);int mem_tot = json_integer_value (json_object_get (ram_status, "Total" ));int mem_free = json_integer_value (json_object_get (ram_status, "Free" ));int mem_buff = json_integer_value (json_object_get (ram_status, "Buffers"));int mem_cach = json_integer_value (json_object_get (ram_status, "Cached" ));int mem_not_used = mem_free + mem_buff + mem_cach;int mem_used = mem_tot - mem_not_used;sprintf(buff, "Memory: %.1f MB used, %.1f MB free", mem_used/1024.0, mem_not_used/1024.0);
...
}
If you need the complete source code, please add the WeChat number (c17865354792)
运行结果:
打开两个客户端连接服务器,最后再同时断开连接服务器。



在客户端的请求消息报告中,作为响应,服务器给出系统当前状态的描述。
总结
多线程在解决方案中提供了并发性。由于并发性,客户端不必等待轮到他们,可以立即得到服务。当服务器有一个线程来处理新连接。接受这样的连接后,将创建一个新线程,负责与给定客户端的所有通信。最后要讲的是,熟悉多线程编程是一项重要的个人技能,只有掌握了多线程编程,才能更合理地选择使用或不使用多线程。
Welcome to follow WeChat official account【程序猿编码】
相关文章:
Linux C/C++ 多线程TCP/UDP服务器 (监控系统状态)
Linux环境中实现并发TCP/IP服务器。多线程在解决方案中提供了并发性。由于并发性,它允许多个客户端同时连接到服务器并与服务器交互。 Linux多线程编程概述 许多应用程序同时处理多项杂务。服务器应用程序处理并发客户端;交互式应用程序通常在处理后台…...
【JavaScript】JavaScript基本使用方法
如何回复程序员发来的短信:Hello world —hello nerd. 前言: 大家好,我是程序猿爱打拳。今天我给大家讲解的是初识JavaScript中基本组成成分、引入方法、输入输出语句,并用源码与效果图的方式展示给大家。 目录 1.JavaScript组成…...
Python数据容器、list列表、tuple元组、str字符串、数据容器(序列)切片、set集合、dict字典、字符串大小比较
数据来源 01 数据容器 为什么学习数据容器 数据容器 总结 02 列表 1)列表定义 为什么需要列表 列表的定义语法 列表的定义方式 演示 """ 演示数据容器之:list列表 语法:[元素,元素,......] """ # 定义一个列表list my_list …...
Python urllib
Python urllib Python urllib 库用于操作网页 URL,并对网页的内容进行抓取处理。 本文主要介绍 Python3 的 urllib。 urllib 包 包含以下几个模块: urllib.request - 打开和读取 URL。urllib.error - 包含 urllib.request 抛出的异常。urllib.parse …...
Centos7安装Python3
前言系统版本:Centos7.6python版本: python 3.10.4下载python下载链接:直通车找到对应版本的python安装包,这里以python 3.10.4为例点击3.10.4版本的链接,拉到最下面找到Files中对应的linux安装包鼠标右键复制下载链接登录linux系…...
[U3D ShaderGraph] 全面学习ShaderGraph节点 | 第四课 | Input/Lighting
📣📣📣本专栏所有内容在完结之前全部为试读模式,专栏完结之后会取消试读模式,如果感觉内容还不错的话请支持一下📣📣📣 ShaderGraph是可视化的着色器编辑工具。您可以使用此工具以可视方式创建着色器。 本专栏可以让你更了解ShaderGraph中每个节点的功能,更自如的…...
SpringBoot升级到3.0
SpringBoot 3.0出来有一段时间了,一直没时间来整理,这次来看一下吧。 Spring Boot 可以轻松创建独立的、生产级的基于 Spring 的应用程序,您可以“直接运行”。 SpringBoot升级到3.01. SpringBoot的维护时间线2. pom添加3. 打包大小对比4. 升…...
JavaWeb8-线程安全问题
目录 1.概念 1.1.单线程 1.2.多线程 2.导致线程不安全的5个因素 ①抢占式执行(首要原因) ②多个线程同时修改了同一个变量 ③非原子性操作 ④内存可见性 ⑤指令重排序 线程优点:加速程序性能。线程缺点:存在安全问题。 1…...
进程切换-
实验课之前有一些问题 中断机制 第一个问题: interrupt的两个状态源头: 外中断多由随机中断(异步中断)造成,如鼠标点击,键盘输入; 内终端多由故障终端:程序运行异常,硬件…...
python--matplotlib(2)
前言 Matplotlib画图工具的官网地址是 http://matplotlib.org/ Python环境下实现Matlab制图功能的第三方库,需要numpy库的支持,支持用户方便设计出二维、三维数据的图形显示,制作的图形达到出版级的标准。 实验环境 Pycharm2020.2.5社区版,w…...
【李忍考研传】五、信心
这天,何隐一来到图书馆就一脸兴奋地对李忍说:“晚上告诉你一个好消息。”李忍又期待又迷惑。“小何今天是咋的了?买彩票中了二十?”虽然李忍很想知道何隐在卖什么关子,但是既然晚上就能知道,那就忍忍吧。 …...
Web 页面之间传递参数的几种方法
Web 页面之间传递参数的方法有很多种,下面列出一些常见的方法以及它们的代码示例。 一、前端直接传递参数 1、URL 参数传递(query string):通过 URL 的查询字符串(即问号后面的参数)将参数传递给页面。可…...
Android实例仿真之二
目录 三 从无入手 第一阶段 第二阶段 第三阶段 第四阶段 第五阶段 第六阶段 第七阶段 八 举两个典型例子: 九 逆向工程 三 从无入手 这节标题叫从无入手,什么意思呢?如果没有Android这个实例存在,你要做一个类似Android…...
day47【代码随想录】动态规划之买卖股票的最佳时机III、买卖股票的最佳时机IV、最佳买卖股票时机含冷冻期、买卖股票的最佳时机含手续费
文章目录前言一、买卖股票的最佳时机III(力扣123)二、买卖股票的最佳时机IV(力扣188)三、最佳买卖股票时机含冷冻期(力扣309)四、买卖股票的最佳时机含手续费(力扣714)股票买卖问题总…...
网络数据包接收流程
1. 网络数据包接收流程简述 典型的以太网卡网络包接收流程如下: 1.网络包通过物理介质传到接收端的phy芯片; 2.phy芯片通过RGMII协议传到MAC芯片rx queue fifo中; 3.MAC芯片通过专用DMA将网络包搬运到网卡驱动程序预先分配好的rx ringbuffer中…...
CSAPP学习笔记——虚拟内存(二)
案例研究 Intel Core i7 该处理底层的Haswell微体系结构允许64位的虚拟和物理地址空间,而现在的Core i7实现支持48位(256TB)虚拟地址空间和52位(4PB)物理地址空间,这对目前来说已经完全够用了。ÿ…...
面试sql
创建表 create table Student ( Sno varchar(20) primary key,Sname varchar(20) UNIQUE,Ssex varchar(2),Sbirthday date,class varchar(20) )create table Course ( Cno varchar(20) primary key,Cname varchar(20) UNIQUE,Tno varchar(20) )create table Score ( …...
Python编程自动化办公案例(2)
作者简介:一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页 目录 前言 一.前期代码 二.实现批量读取 1.os库 2.实现思路 (1&#…...
Vulnhub 渗透练习(七)—— FRISTILEAKS: 1.3
环境搭建 下载链接 virtualbox 打开靶机设置为 host-only,攻击机同样。 具体可点此处 信息收集 开了个 80 端口。 用的是 apache 2.2.15 ,这个版本有个解析漏洞。 目录 根据首页的图片猜测 /fristi/ 目录(不过我没想到 -_-&#x…...
阶段二10_面向对象高级_分类分包思想和案例环境搭建
一.分类思想 1.分类思想概念: 分工协作,专人干专事 2.信息管理系统分类[案例] Student 类-------------------->标准学生类,封装键盘录入的学生信息(id , name , age , birthday) StudentDao 类-----------------&…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
