作业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…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
