当前位置: 首页 > news >正文

作业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;
}

http://www.lryc.cn/news/409030.html

相关文章:

  • 自定义webIpad证件相机(webRTC)
  • GO发票真伪批量查验方法、数电票查验接口
  • 【Go系列】Go的UI框架Fyne
  • .NET MAUI:跨平台开发的未来
  • VSCode切换默认终端
  • 卫星观测叶绿素的相反信号
  • 2024年最新NVIDIA T4价格表及行业趋势!
  • HTML + CSS编程规范
  • 机器学习之人脸识别-使用 scikit-learn 和人工神经网络进行高效人脸识别
  • 【虚拟化】KVM概念和架构
  • 【Linux】权限2
  • 汽车长翅膀:GPU 是如何加速深度学习模型的训练和推理过程的?
  • 怀旧必玩!重返童年,扫雷游戏再度登场!
  • Avalonia中的路由事件
  • ubuntu20.04安装RabbitMQ +Erlang
  • 【word转pdf】【最新版本jar】Java使用aspose-words实现word文档转pdf
  • 分布式:RocketMQ/Kafka总结(附下载链接)
  • Air780EP模块 LuatOS开发-MQTT接入阿里云应用指南
  • 【算法】插入区间
  • C++ 代码实现socket 类使用TCP/IP进行通信 (windows 系统)
  • 前后端分离项目部署,vue--nagix发布部署,.net--API发布部署。
  • 【BUG】已解决:UnicodeDecodeError: ‘utf-8’ codec can’t decode bytes in position 10
  • C++ | QQ后端暑期实习面试
  • 实用网站推荐
  • Linux |Nethogs 监控网络使用情况
  • 大语言模型训练过程中,怎么实现算力共享,采用什么分片规则和共享策略
  • JCR一区级 | Matlab实现TTAO-Transformer-LSTM多变量回归预测
  • 斐波那契数列(Fibonacci)数列 c++详解
  • 第三届人工智能、物联网和云计算技术国际会议(AIoTC 2024,9月13-15)
  • 家具购物小程序的设计