基于线程池的TCP套接字通信

基于线程池的TCP套接字通信

还是只改变server.cpp

其中main函数, 也就是主线程中的处理流程:

  • 创建监听的套接字
  • 绑定IP和端口
  • 设置监听
  • 创建线程池实例对象
  • 添加监听任务 acceptConn
  • 主线程退出

监听任务函数的处理流程如下:

  • 阻塞等待并接受客户端连接
  • 检测有客户端连接时, 添加通信任务worker
  • 释放资源

通信任务函数的处理流程:

  • 打印客户端的信息
  • 和客户端通信
  • 释放资源

其中添加监听和通信任务函数的时候的参数问题需要创建两个结构体, 具体细节在代码中已经体现出来了

//
// Created by 47468 on 2024/1/22.
//
#include <iostream>
#include "arpa/inet.h"
using namespace std;
#include "cstring"
#include "unistd.h"
#include "pthread.h"
#include "ThreadPool.h"// 监听任务函数传递给通信任务函数参数时用到的结构体
struct SockInfo{int fd; // 通信描述符pthread_t tid; // 子线程的线程idstruct sockaddr_in addr; // 把客户端的ip和端口信息传递给通信任务函数
};// 主函数传递给监听任务函数参数时用到的结构体
struct PoolInfo{ThreadPool* pool; // 主线程中创建的线程池实例int fd; // 监听描述符
};// 函数声明
void acceptConn(void* arg);
void worker(void* arg);int main() {// 1. 创建监听的套接字int lfd = socket(AF_INET, SOCK_STREAM, 0);if (lfd == -1) {perror("socket");exit(0);}// 2. 将socket()返回值和本地的IP端口绑定到一起sockaddr_in addr{}; // 初始化列表addr.sin_family = AF_INET;addr.sin_port = htons(10000);// INADDR_ANY代表本机的所有IP, 假设有三个网卡就有三个IP地址// 这个宏可以代表任意一个IP地址// 这个宏一般用于本地的绑定操作addr.sin_addr.s_addr = INADDR_ANY;// inet_pton(AF_INET, "192.168.237.131", &addr.sin_addr.s_addr);int ret = bind(lfd, (struct sockaddr *) &addr, sizeof(addr));if (ret == -1) {perror("bind");exit(0);}// 3. 设置监听ret = listen(lfd, 128);if (ret == -1) {perror("listen");exit(0);}// 创建线程池auto* pool = new ThreadPool(3, 10);auto* poolInfo = new PoolInfo;poolInfo->fd = lfd;poolInfo->pool = pool;// 添加监听任务pool->addTask(Task(acceptConn, poolInfo));pthread_exit(nullptr);
}// 监听任务函数
void acceptConn(void* arg){auto* poolInfo = static_cast<PoolInfo*>(arg);// 4. 阻塞等待并接受客户端连接int len = sizeof(sockaddr);while (true) {auto* pinfo = new SockInfo;pinfo->fd = accept(poolInfo->fd, (struct sockaddr *) &pinfo->addr, (socklen_t *) (&len));if (pinfo->fd == -1) {perror("accept");
//            exit(0);break;}// 添加通信任务poolInfo->pool->addTask(Task(worker, pinfo));}// 释放资源close(poolInfo->fd);
}// 通信任务函数
void worker(void* arg){auto* info = static_cast<SockInfo*>(arg);// 打印子线程idcout << "子线程id: " << info->tid << endl;// 打印客户端的地址信息char ip[24] = {0};cout << "客户端的ip地址: " << inet_ntop(AF_INET, &info->addr.sin_addr.s_addr, ip, sizeof(ip))<< ", 端口: " << ntohs(info->addr.sin_port) << endl;// 5. 和客户端通信while(true){// 接收数据char buf[1024];memset(buf, 0, sizeof(buf));auto len = read(info->fd, buf, sizeof(buf));if(len > 0){cout << "客户端say: " << buf << endl;write(info->fd, buf, len);} else if (len == 0){cout << "客户端断开了连接" << endl;break;} else {perror("read");break;}}close(info->fd);
}

客户端的代码和线程池代码在之前的文章里已经有了, 都不变

测试情况:

在这里插入图片描述

在这里插入图片描述

实现了一台服务器和4个客户端的通信(最多的时候5个线程), 因为我们输入参数中最少三个线程, 所以在最后只删除了两个线程, 留有三个live线程, 其中一个主线程是busy线程, 还有两个线程没事做

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/422337.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flutter3使用dio库发送FormData数据格式时候的坑,和get库冲突解决办法

问题描述 问题1&#xff1a;当你使用FormData.from(Flutter3直接不能用)的时候&#xff0c;可能会提示没有这个方法&#xff0c;或者使用FormData.fromMap(flutter3的dio支持)的时候也提示没有&#xff0c;这时候可能就是和get库里面的Formdata冲突了 问题1&#xff1a;The me…

【Linux】第三十二站:命名管道

文章目录 一、命名管道介绍二、编码1.mkfifo2.unlink3.一个简单的例子4.修改 一、命名管道介绍 管道应用的一个限制就是只能在具有共同祖先&#xff08;具有亲缘关系&#xff09;的进程间通信。 如果我们想在不相关的进程之间交换数据&#xff0c;可以使用FIFO文件来做这项工作…

​第14节-高质量简历写作求职通关-在线测试

在线测试主要包括性格测试、综合能力测试、技能测试三类 性格测试 性格测试主要用于考察个人与工岗位的匹配程度 考察内容包含性格、能力、动机、价值观等&#xff0c;考察形式一般为给出相应的工作场景&#xff0c;让你选择最喜欢或者最不喜欢的答案 技能考试 这类测试一般是针…

数学建模--PageRank算法的Python实现

文章目录 1. P a g e R a n k PageRank PageRank算法背景2. P a g e R a n k PageRank PageRank算法基础2.1. P a g e R a n k PageRank PageRank问题描述2.2.有向图模型2.3.随机游走模型 3. P a g e R a n k PageRank PageRank算法定义3.1. P a g e R a n k PageRank PageRank…

【spring】代码生成器

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;spring ⛺️稳中求进&#xff0c;晒太阳 代码生成器&#xff08;本质IO流&#xff09; 在mybatis的逆向工程生成model和mapper接口和xml文件后&#xff0c;还需要反复的写Service的接口和…

mac 安装配置oh-my-zsh

1. 安装brew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 按照步骤安装即可 安装完成查看版本 brew -v 2. 安装zsh brew install zsh 查看版本 zsh --version 3. 安装oh-my-zsh github官网链…

反序列化字符串逃逸(上篇)

首先&#xff0c;必须先明白&#xff0c;这个点并不难&#xff0c;我给大家梳理一遍就会明白。 反序列化字符串逃逸就是序列化过程中逃逸出来字符&#xff0c;是不是很简单&#xff0c;哈哈哈&#xff01; 好了&#xff0c;不闹了&#xff0c;其实&#xff1a; 这里你们只要懂…

JavaEE中的监听器的作用和工作原理

在JavaEE&#xff08;Java Platform, Enterprise Edition&#xff09;中&#xff0c;监听器&#xff08;Listener&#xff09;是一种重要的组件&#xff0c;用于监听和响应Web应用程序中的事件。监听器的作用是在特定的事件发生时执行一些自定义的逻辑。常见的监听器包括Servle…

深度学习记录--梯度消失和爆炸

梯度消失和爆炸的产生 当神经网络层数很大时&#xff0c;即很大时&#xff0c;w与1之间的大小关系会产生梯度消失与梯度爆炸的问题 当w<1时&#xff0c;会非常小&#xff0c;梯度消失 当w>1时&#xff0c;会非常大&#xff0c;梯度爆炸 解决方法 权重初始化 层数n越大…

网络安全全栈培训笔记(57-服务攻防-应用协议RsyncSSHRDPFTP漏洞批量扫描口令拆解)

第57天 服务攻防-应用协议&Rsync&SSH&RDP&FTP&漏洞批量扫描&口令拆解 知识点&#xff1a; 1、服务攻防-远程控制&文件传输等 2、远程控制-RDP&RDP&弱口令&漏洞 3、文件传输-FTP&Rsyc&弱口令&漏洞 章节内容&#xff1a;…

1.21 day6 IO网络编程

网络聊天室 服务端 #include <myhead.h> #define PORT 8888 #define IP "192.168.122.48" struct MSG {char tyep;char name[20];char buf[128]; }; typedef struct Node {struct sockaddr_in cin;struct Node*next; }*node;int main(int argc, const char *…

HarmonyOS ArkUI 框架的实现原理和落地实践

HarmonyOS 操作系统特性 首先介绍一下鸿蒙操作系统&#xff0c;鸿蒙操作系统是华为设计的下一代分布式物联网操作系统&#xff0c;它首次引入了面向场景设计的分布式理念&#xff0c;同时能够实现一套操作系统通过裁减的方式适配到某种终端&#xff0c;它是华为面向万物互联理念…