UDP的双向通信
双向交替通信(Alternating Bidirectional Communication):在这种方式下,通过约定一方作为发送方,一方作为接收方,双方交替发送和接收数据。例如,一方发送数据报给另一方,然后等待对方的回应,对方接收数据报后进行处理,然后发送回应给发送方,交替进行下去。
UDP 客户端-服务器通信代码说明
概述
本文档提供了用 C 语言编写的简单 UDP 客户端-服务器通信系统的概览和使用说明。服务器接收来自客户端的消息,允许用户输入响应,并将其发送回客户端。客户端向服务器发送消息并显示服务器的响应。
- 服务器代码
服务器代码设置了一个 UDP 套接字,绑定到指定端口,并监听来自客户端的消息。收到消息后,它会提示用户输入回复,然后将回复发送回客户端。
- 客户端代码
客户端代码建立了一个 UDP 套接字,并向服务器的 IP 地址和端口发送消息。然后,它等待服务器的响应并将其打印出来。
限制和改进
- 限制:
- 阻塞 I/O:客户端和服务器都使用阻塞 I/O 操作(
recvfrom
和sendto
)。这意味着服务器一次只能处理一个客户端,客户端必须等待服务器的响应才能继续。 - 无并发处理:服务器不支持同时处理多个客户端,这限制了其可扩展性。
- 硬编码值:IP 地址和端口被硬编码,这降低了灵活性和可重用性。
- 缺乏错误处理:网络操作几乎没有错误处理,可能导致崩溃或未定义的行为。
- 安全性:代码没有实现任何加密或认证,使其容易受到拦截和未经授权的访问。
- 改进:
- 非阻塞 I/O 或多线程:实现非阻塞 I/O 或使用多线程同时处理多个客户端。
- 配置文件:使用配置文件或命令行参数来指定 IP 地址和端口。
- 健壮的错误处理:添加全面的错误处理,以优雅地管理网络错误。
- 安全增强:集成加密(如 TLS)和认证机制来保护通信。
- 用户界面:为服务器开发一个用户友好的界面,以更有效地管理收到的消息和回复。
使用说明
- 编译:服务端
**gcc UDP_server.c -o server**
客户端**gcc UDP_client.c -o client**
- 首先运行服务器程序,确保它正在监听传入的消息。
- 执行客户端程序,向服务器发送消息并接收回复。
- 本次所写的代码只能实现1:1的回复。
相关代码
服务端代码
- 初始化变量:定义套接字描述符 sockfd,缓冲区 buffer 和 reply,以及服务器和客户端的地址结构 servaddr 和 cliaddr。
- 创建套接字:调用 socket() 函数创建一个 UDP 套接字。
- 设置服务器地址:将服务器地址结构 servaddr 清零,并设置地址族为 IPv4 (AF_INET),IP 地址设置为 INADDR_ANY(接受任何来自本机的 IP 地址),端口号设置为 PORT。
- 绑定套接字:使用 bind() 函数将 sockfd 绑定到服务器的 IP 地址和端口号。
- 处理客户端消息:进入一个无限循环,使用 recvfrom() 函数接收来自客户端的消息,并将其存储在 buffer 中。
- 获取并发送回复:提示用户输入回复消息,使用 fgets() 从标准输入读取字符串,然后使用 sendto() 函数将回复发送给客户端。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 12345
#define MAXLINE 1024
int main() {
int sockfd;
char buffer[MAXLINE];
char reply[MAXLINE];
struct sockaddr_in servaddr, cliaddr;
// 创建UDP套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// 填充服务器信息
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// 绑定套接字与地址
if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
while (1) {
socklen_t len = sizeof(cliaddr);
int n = recvfrom(sockfd, buffer, MAXLINE, 0, (struct sockaddr *) &cliaddr, &len);
buffer[n] = '\0'; // null terminate
printf("Client's message: %s\n", buffer);
// 获取服务器的回复
printf("Enter reply message: ");
fgets(reply, MAXLINE, stdin);
// 移除换行符
reply[strcspn(reply, "\n")] = 0;
// 回复客户端
sendto(sockfd, reply, strlen(reply), 0, (struct sockaddr *) &cliaddr, len);
printf("Reply sent to client.\n");
}
// 关闭套接字
close(sockfd);
return 0;
}
客户端代码
- 初始化变量:定义套接字描述符 sockfd,发送和接收缓冲区 sendline 和 recvline,以及服务器地址结构 servaddr。
- 创建套接字:调用 socket() 函数创建一个 UDP 套接字。
- 设置服务器地址:将服务器地址结构 servaddr 清零,并设置地址族为 IPv4 (AF_INET),服务器 IP 地址和端口号。
- 发送和接收消息:进入一个无限循环,使用 fgets() 函数从标准输入获取消息,然后使用 sendto() 函数发送消息给服务器。之后,使用 recvfrom() 函数接收服务器的回复。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SERVER_PORT 12345
#define SERVER_IP "127.0.0.1"
#define MAXLINE 1024
int main() {
int sockfd;
struct sockaddr_in servaddr;
char sendline[MAXLINE], recvline[MAXLINE + 1];
socklen_t len;
// 创建UDP套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// 填充服务器信息
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVER_PORT);
servaddr.sin_addr.s_addr = inet_addr(SERVER_IP);
while (1) {
printf("Enter the message to send: ");
fgets(sendline, MAXLINE, stdin);
// 发送消息给服务器
sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *) &servaddr, sizeof(servaddr));
// 接收服务器的回复
len = sizeof(servaddr);
int n = recvfrom(sockfd, recvline, MAXLINE, 0, (struct sockaddr *) &servaddr, &len);
recvline[n] = '\0'; // null terminate
printf("Server's reply: %s\n", recvline);
}
// 关闭套接字
close(sockfd);
return 0;
}
标签:UDP,双向通信,sockfd,服务器,接字,include,servaddr,客户端 From: https://www.cnblogs.com/banon/p/18241044