作业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…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
动态规划-1035.不相交的线-力扣(LeetCode)
一、题目解析 光看题目要求和例图,感觉这题好麻烦,直线不能相交啊,每个数字只属于一条连线啊等等,但我们结合题目所给的信息和例图的内容,这不就是最长公共子序列吗?,我们把最长公共子序列连线起…...
