全双工: 通信双方 既可以发送,也可以接收数据
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); // 创建socket
if (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; // 线程ID
if (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); // 关闭socket
return 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; // 线程ID
sock = socket(AF_INET , SOCK_STREAM , 0); // 创建socket
if (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) { // 绑定socket
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("接受连接失败");
return 1;
}
if (pthread_create(&thread_id, NULL, server_recv_thread, &client_sock) != 0) { // 创建接收线程
perror("创建线程失败");
return 1;
}
}
close(sock); // 关闭socket
return 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; // 获取客户端socket
char 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); // 如果客户端断开,关闭socket
free(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; // 当前线程数量
// 创建服务器socket
sock = 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); // 如果线程池已满,关闭新连接的socket
continue;
}
// 分配并初始化客户端信息结构体
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);
}
// 关闭服务器socket
close(sock);
// 正常退出
return 0;
}
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » 作业7.26~28
发表评论 取消回复