作业7.26~28
全双工: 通信双方 既可以发送,也可以接收数据
1. 利用多线程 或者 多进程, 实现TCP服务器 和 客户端的全双工通信
思路:
服务器和客户端, 在建立通信以后,可以创建线程,在线程编写另一个功能代码
客户端参考:
pthread_handler()
{while(1){fgets();send(); }
}main()
{socket();connect();pthread_create();while(1){recv(); }
}服务器参考:
pthread_handler()
{while(1){ fgets();send(); }
}main()
{socket();bind();listen();accept();pthread_create();while(1){recv(); }
}
客户端示例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>#define BUFFER_SIZE 1024// 接收线程函数
void *client_recv_thread(void *arg) {int sock = *(int *)arg; // 从参数中获取socket描述符char buffer[BUFFER_SIZE]; // 用于接收数据的缓冲区while (1) {memset(buffer, 0, BUFFER_SIZE); // 清空缓冲区ssize_t bytes_received = recv(sock, buffer, BUFFER_SIZE - 1, 0); // 接收数据if (bytes_received <= 0) {perror("接收数据失败");break; // 如果接收失败,结束线程}printf("收到信息: %s", buffer); // 打印接收到的信息}pthread_exit(NULL); // 结束线程
}int main() {int sock; // 客户端socket描述符struct sockaddr_in server; // 服务器地址结构char buffer[BUFFER_SIZE]; // 用于发送数据的缓冲区sock = socket(AF_INET, SOCK_STREAM, 0); // 创建socketif (sock == -1) {perror("无法创建socket");return 1;}server.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP地址server.sin_family = AF_INET; // 设置为Internet协议族server.sin_port = htons(8888); // 设置服务器端口if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) { // 连接到服务器perror("连接失败");return 1;}pthread_t thread_id; // 线程IDif (pthread_create(&thread_id, NULL, client_recv_thread, &sock) != 0) { // 创建接收线程perror("创建线程失败");return 1;}while (1) { // 主循环,用于发送数据printf("输入信息: ");fgets(buffer, BUFFER_SIZE, stdin); // 从标准输入读取一行send(sock, buffer, strlen(buffer), 0); // 发送数据}close(sock); // 关闭socketreturn 0;
}
服务器代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>#define MAX_THREADS 10
#define BUFFER_SIZE 1024// 接收线程函数
void *server_recv_thread(void *arg) {int sock = *(int *)arg; // 从参数中获取socket描述符char buffer[BUFFER_SIZE]; // 用于接收数据的缓冲区while (1) {memset(buffer, 0, BUFFER_SIZE); // 清空缓冲区ssize_t bytes_received = recv(sock, buffer, BUFFER_SIZE - 1, 0); // 接收数据if (bytes_received <= 0) {perror("接收数据失败");break; // 如果接收失败,结束线程}printf("收到信息: %s", buffer); // 打印接收到的信息}pthread_exit(NULL); // 结束线程
}int main() {int sock, client_sock; // 服务器socket描述符,客户端socket描述符struct sockaddr_in server, client; // 服务器和客户端地址结构pthread_t thread_id; // 线程IDsock = socket(AF_INET , SOCK_STREAM , 0); // 创建socketif (sock == -1) {perror("无法创建socket");return 1;}server.sin_family = AF_INET; // 设置为Internet协议族server.sin_addr.s_addr = INADDR_ANY; // 监听所有可用接口server.sin_port = htons(8888); // 设置服务器端口if (bind(sock, (struct sockaddr *)&server , sizeof(server)) < 0) { // 绑定socketperror("绑定失败");return 1;}listen(sock, 3); // 开始监听连接printf("等待接收连接...\n");while (1) { // 主循环,用于接受新连接socklen_t len = sizeof(struct sockaddr_in); // 地址长度client_sock = accept(sock, (struct sockaddr *)&client, &len); // 接受连接if (client_sock < 0) {perror("接受连接失败");return 1;}if (pthread_create(&thread_id, NULL, server_recv_thread, &client_sock) != 0) { // 创建接收线程perror("创建线程失败");return 1;}}close(sock); // 关闭socketreturn 0;
}
TCP建立的初衷是 1 对 1 的通信, 其本身机制无法完成并发服务器
只能借助其他方法。。。。。
这里不要求实现全双工
2. 利用多线程 或者 多进程,实现TCP服务器 可以同时跟多个客户端通信(并发服务器)
思路:
每次accept建立通信, 服务器都创建一个专属的线程任务,与客户端通信;
服务器在通信时,主要依靠的是acceptfd,每次acceptfd的值都代表不同的通信套接字;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>#define MAX_THREADS 10 // 线程池中线程的最大数量
#define BUFFER_SIZE 1024 // 缓冲区大小// 客户端信息结构体
typedef struct {int sock; // 客户端socket描述符
} client_info;// 客户端处理线程函数
void *handle_client(void *arg) {client_info *info = (client_info *)arg; // 从参数中获取客户端信息int client_sock = info->sock; // 获取客户端socketchar buffer[BUFFER_SIZE]; // 缓冲区,用于接收和发送数据// 循环接收并处理客户端数据while (1) {memset(buffer, 0, BUFFER_SIZE); // 清空缓冲区ssize_t bytes_received = recv(client_sock, buffer, BUFFER_SIZE - 1, 0); // 接收数据if (bytes_received <= 0) {printf("客户端断开连接\n");close(client_sock); // 如果客户端断开,关闭socketfree(info); // 释放客户端信息结构体pthread_exit(NULL); // 结束线程} else {printf("接收到客户端信息: %s", buffer); // 打印接收到的信息send(client_sock, buffer, bytes_received, 0); // 将接收到的数据原样返回给客户端}}
}int main() {int sock, client_sock; // 服务器和客户端socket描述符struct sockaddr_in server, client; // 服务器和客户端地址信息pthread_t thread_id[MAX_THREADS]; // 线程ID数组int active_threads = 0; // 当前线程数量// 创建服务器socketsock = socket(AF_INET, SOCK_STREAM, 0);if (sock == -1) {perror("无法创建socket");return 1;}// 设置服务器地址信息server.sin_family = AF_INET;server.sin_addr.s_addr = INADDR_ANY;server.sin_port = htons(8888);// 绑定服务器地址if (bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {perror("绑定失败");return 1;}// 开始监听连接listen(sock, 3);printf("等待接收连接...\n");// 主循环,用于接受新连接while (1) {socklen_t len = sizeof(struct sockaddr_in);client_sock = accept(sock, (struct sockaddr *)&client, &len);if (client_sock < 0) {perror("接受连接失败");continue;}// 检查线程池是否已满if (active_threads >= MAX_THREADS) {printf("线程数量已达到上限,拒绝连接\n");close(client_sock); // 如果线程池已满,关闭新连接的socketcontinue;}// 分配并初始化客户端信息结构体client_info *info = malloc(sizeof(client_info));info->sock = client_sock;// 创建线程处理新连接if (pthread_create(&thread_id[active_threads], NULL, handle_client, info) != 0) {perror("创建线程失败");continue;}// 增加活动线程数量active_threads++;}// 等待所有线程结束for (int i = 0; i < active_threads; i++) {pthread_join(thread_id[i], NULL);}// 关闭服务器socketclose(sock);// 正常退出return 0;
}
相关文章:
作业7.26~28
全双工: 通信双方 既可以发送,也可以接收数据 1. 利用多线程 或者 多进程, 实现TCP服务器 和 客户端的全双工通信 思路: 服务器和客户端, 在建立通信以后,可以创建线程,在线程编写另一个功能代…...

自定义webIpad证件相机(webRTC)
该技术方案可用于各浏览器自定义相机开发 相机UI(index.html) <!DOCTYPE html> <html lang"zh" prew"-1"><head><meta charset"UTF-8"><meta name"viewport"content"user-sc…...
GO发票真伪批量查验方法、数电票查验接口
“教”给机器标注数据的正确率就决定了人工智能判断的正确率。翔云人工智能开放平台的OCR产品经过我们的开发人员精心调“教”,识别率高、识别速度快。 发票,是发生的成本、费用或收入的原始凭证。于公司来说,发票主要是公司做账的依据&…...

【Go系列】Go的UI框架Fyne
前言 总有人说Go语言是一门后端编程语言。 Go虽然能够很好地处理后端开发,但是者不代表它没有UI库,不能做GUI,我们一起来看看Go怎么来画UI吧。 正文 Go语言由于其简洁的语法、高效的性能和跨平台的编译能力,非常适合用于开发GUI…...
.NET MAUI:跨平台开发的未来
常用资源 (1).NET MAUI8构建应用文档。 Build your first .NET MAUI app - .NET MAUI | Microsoft Learn 一、什么是 .NET MAUI? .NET Multi-platform App UI (.NET MAUI) 是微软推出的一款跨平台开发框架。作为 Xamarin.Forms 的下一代产…...

VSCode切换默认终端
我的VSCode默认终端为PowerShell,每次新建都会自动打开PowerShell。但是我想让每次都变为cmd,也就是Command Prompt 更改默认终端的操作方法如下: 键盘调出命令面板(CtrlShiftP)中,输入Terminal: Select Default Prof…...
卫星观测叶绿素的相反信号
Contrasted Trends in Chlorophyll-a Satellite Products 运用卫星产品研究Chl的长时间序列变化时需要注意 Introduction (1)研究叶绿素的长期变化,需要至少40年的长时间序列; (2)Tian and Zhang 2023报告…...

2024年最新NVIDIA T4价格表及行业趋势!
英伟达(NVIDIA)作为目前全球T0级别的GPU制造商,其T4系列显卡以其卓越的计算性能和能效比,在数据中心、云计算及AI领域占据重要地位。 一、NVIDIA T4价格表概览 在探讨NVIDIA T4显卡的价格时,我们需要从直接购买和租赁…...
HTML + CSS编程规范
编程规范 HTML CSS 命名规范 HTML CSS 命名规范 1. 命名需要是具备语义性的单词,不能用 数字 拼音 数字,符号开头正确示范 : wrap description title content错误示范 : aaaa a1 $we 4tdds 2. 命名需要多个单词连接的情况下, 标记语言中可以使用 …...

机器学习之人脸识别-使用 scikit-learn 和人工神经网络进行高效人脸识别
文章摘要 本文将介绍如何使用 Python 的 scikit-learn 库和人工神经网络(ANN)来识别人脸。我们将使用 LFW 数据集(Labeled Faces in the Wild),这是一个广泛用于人脸识别基准测试的大型人脸数据库。我们将展示如何准备…...

【虚拟化】KVM概念和架构
目录 一、什么是KVM? 二、KVM的功能 2.1 主要的功能 2.2 其它功能 三、KVM核心组件及作用 四、KVM与VMware的优势 五、KVM架构 六、qemu介绍 七、创建虚拟机流程 一、什么是KVM? Kernel-based Virtual Machine的简称,KVM 是基于虚拟…...

【Linux】权限2
Linux文件要被执行满足两个条件: ①必须要具备可执行权限 x ②真的是一个可执行程序 1.权限的修改,文件强行给别人 权限就是拦住一批人,不让他做特定的一件事情 a.更改人,更改文件所隶属的人 如果把文件强行给别人, chown xxx(普通用户) xxx(文件名) 会出现下面的情况 很明显…...

汽车长翅膀:GPU 是如何加速深度学习模型的训练和推理过程的?
编者按:深度学习的飞速发展离不开硬件技术的突破,而 GPU 的崛起无疑是其中最大的推力之一。但你是否曾好奇过,为何一行简单的“.to(‘cuda’)”代码就能让模型的训练速度突飞猛进?本文正是为解答这个疑问而作。 作者以独特的视角&…...

怀旧必玩!重返童年,扫雷游戏再度登场!
Python提供了一个标准的GUI(图形用户界面)工具包:Tkinter。它可以用来创建各种窗口、按钮、标签、文本框等图形界面组件。 而且Tkinter 是 Python 自带的库,无需额外安装。 Now,让我们一起来回味一下扫雷小游戏吧 扫…...
Avalonia中的路由事件
文章目录 一、路由事件的基本概念事件路由机制事件的生命周期二、创建路由事件定义路由事件触发路由事件处理路由事件三、使用路由事件的场景用户输入控件交互动画和样式数据绑定和验证四、路由事件的优缺点优点:缺点:五、总结在Avalonia中,路由事件是处理用户交互和控件之间…...
ubuntu20.04安装RabbitMQ +Erlang
ubuntu20.04安装RabbitMQ 3.11.19Erlang 25.3.1_ubuntu20.04.6 安装 rabbitmq-CSDN博客 LINUX下载编译libpng_linux libpng下载-CSDN博客 Ubuntu20.04 安装 Nginx 软件报错:libgd3 缺少 libpng12-0 依赖 Ubuntu安装RabbitMq(保姆级教学,直…...

【word转pdf】【最新版本jar】Java使用aspose-words实现word文档转pdf
【aspose-words-22.12-jdk17.jar】word文档转pdf 前置工作1、下载依赖2、安装依赖到本地仓库 项目1、配置pom.xml2、配置许可码文件(不配置会有水印)3、工具类4、效果 踩坑1、pdf乱码2、word中带有图片转换 前置工作 1、下载依赖 通过百度网盘分享的文…...

分布式:RocketMQ/Kafka总结(附下载链接)
文章目录 下载链接思维导图 本文总结的是关于消息队列的常见知识总结。消息队列和分布式系统息息相关,因此这里就将消息队列放到分布式中一并进行处理关联 下载链接 链接: https://pan.baidu.com/s/1hRTh7rSesikisgRUO2GBpA?pwdutgp 提取码: utgp 思维导图...

Air780EP模块 LuatOS开发-MQTT接入阿里云应用指南
简介 本文简单讲述了利用LuatOS-Air进行二次开发,采用一型一密、一机一密两种方式认证方式连接阿里云。整体结构如图 关联文档和使用工具:LuatOS库阿里云平台 准备工作 Air780EP_全IO开发板一套,包括天线SIM卡,USB线 PC电脑&…...
【算法】插入区间
难度:中等 题目: 给你一个 无重叠的 ,按照区间起始端点排序的区间列表 intervals,其中 intervals[i] [starti, endi] 表示第 i 个区间的开始和结束,并且 intervals 按照 starti 升序排列。同样给定一个区间 newInte…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...

Yolo11改进策略:Block改进|FCM,特征互补映射模块|AAAI 2025|即插即用
1 论文信息 FBRT-YOLO(Faster and Better for Real-Time Aerial Image Detection)是由北京理工大学团队提出的专用于航拍图像实时目标检测的创新框架,发表于AAAI 2025。论文针对航拍场景中小目标检测的核心难题展开研究,重点解决…...

解密鸿蒙系统的隐私护城河:从权限动态管控到生物数据加密的全链路防护
摘要 本文以健康管理应用为例,展示鸿蒙系统如何通过细粒度权限控制、动态权限授予、数据隔离和加密存储四大核心机制,实现复杂场景下的用户隐私保护。我们将通过完整的权限请求流程和敏感数据处理代码,演示鸿蒙系统如何平衡功能需求与隐私安…...
jieba实现和用RNN实现中文分词的区别
Jieba 分词和基于 RNN 的分词在技术路线、实现机制、性能特点上有显著差异,以下是核心对比: 1. 技术路线对比 维度Jieba 分词RNN 神经网络分词范式传统 NLP(规则 统计)深度学习(端到端学习)核心依赖词典…...
【设计模式】1.简单工厂、工厂、抽象工厂模式
every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 以下是 简单工厂模式、工厂方法模式 和 抽象工厂模式 的 Python 实现与对比,结合代码示例和实际应用场景说明: 1. 简单工厂模式&a…...