UDP协议是一种无连接的协议,它比较适合用于短且简单的通讯,UDP协议的通讯质量不保证,但数据传输速度快。而在这种协议下,我们需要实现数据的发送和接收,本文将围绕UDP协议的接收函数recvfrom展开,介绍其使用方法及实例。
首先,让我们来了解一下UDP的通讯机制。UDP协议是面向数据报的,它只关心数据报的传输,而不关心数据是否能够正确地到达目标。UDP的数据采用的是一种封装的形式,封装后的数据称为用户数据报(UDP datagram),它包含了源端口号和目的端口号,以及数据负载。当一台主机需要向其他主机发送UDP数据时,应该按照以下步骤执行:
1. 创建一个UDP套接字
2. 绑定本地地址和端口
3. 使用sendto函数发送UDP数据报
4. 接收对方发送的UDP数据报
其中步骤4即为本文所讲的主题——。
UDP协议的接收函数为recvfrom,其函数原型为:
```
int recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
```
该函数的作用是接收UDP数据报,并根据情况填充发送方的地址信息。其中,sockfd为UDP套接字描述符,buf为用于接收数据的缓存,len为该缓存的大小,flags表示接收时的行为,一般置0即可。src_addr为指向套接字地址结构体的指针,用于存储发送方的地址信息。addrlen为指向存放地址信息长度的整型变量的指针。
下面我们来看一下recvfrom函数的实际应用。假设我们要实现一个简单的UDP客户端和服务端通讯程序,以完成文字消息的发送和接收,客户端发送的消息为“hello”,服务端接收到后回复“world”。其流程图如下所示:

下面是完整的程序代码:
客户端代码(client.c):
```
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8888
#define BUF_SIZE 1024
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in server_addr;
char send_buf[BUF_SIZE];
char recv_buf[BUF_SIZE];
int len;
// 创建UDP套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket error");
exit(EXIT_FAILURE);
}
// 设置服务端地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
server_addr.sin_port = htons(SERVER_PORT);
while(1) {
// 输入消息
printf("Please input message: ");
fgets(send_buf, BUF_SIZE, stdin);
send_buf[strlen(send_buf) - 1] = '\0';
// 发送消息
len = sendto(sockfd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (len < 0) {
perror("sendto error");
break;
}
// 接收回复
len = recvfrom(sockfd, recv_buf, BUF_SIZE, 0, NULL, NULL);
if (len < 0) {
perror("recvfrom error");
break;
}
printf("Server: %s\n", recv_buf);
}
close(sockfd);
return 0;
}
```
服务端代码(server.c):
```
#include
#include
#include
#include
#include
#include
#include
#define SERVER_IP "0.0.0.0"
#define SERVER_PORT 8888
#define BUF_SIZE 1024
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in server_addr, client_addr;
char recv_buf[BUF_SIZE];
char send_buf[] = "world";
int len;
socklen_t addr_len = sizeof(client_addr);
// 创建UDP套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket error");
exit(EXIT_FAILURE);
}
// 设置本地地址和端口
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
server_addr.sin_port = htons(SERVER_PORT);
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("bind error");
exit(EXIT_FAILURE);
}
while(1) {
// 接收消息
len = recvfrom(sockfd, recv_buf, BUF_SIZE, 0, (struct sockaddr*)&client_addr, &addr_len);
if (len < 0) {
perror("recvfrom error");
break;
}
printf("Client: %s\n", recv_buf);
// 回复消息
len = sendto(sockfd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&client_addr, addr_len);
if (len < 0) {
perror("sendto error");
break;
}
}
close(sockfd);
return 0;
}
```
在上述代码中,我们使用了recvfrom函数接收客户端发送的数据,并使用sendto函数将回复发送给客户端。在服务端程序的recvfrom函数参数中,我们传入了一个指向客户端地址结构体的指针,并在函数执行结束后,用该指针返回了客户端地址信息。在客户端程序的recvfrom函数参数中,我们传入了NULL,表示不需要返回发送方的地址信息。
当我们编译并运行上述程序后,我们可以在客户端窗口中输入消息,服务端将接收到这个消息,并回复“world”,客户端将打印出该回复消息,如下图所示:

至此,通过使用recvfrom函数,我们成功地实现了UDP协议通信的接收功能,使得我们可以完整地完成整个UDP通讯的过程。
本文介绍了UDP协议通信中使用recvfrom函数的方法及实例,通过实际的代码演示,我们更加深入地了解了UDP协议的接收机制,并且掌握了如何使用该函数实现UDP协议的接收功能。在实际的UDP通讯中,我们可以根据自己的需要进行改进,以满足不同业务需求。