recvfrom
是一个在 POSIX 兼容操作系统(如 Linux)中用于接收数据的系统调用。它用于接收来自套接字(socket)的数据,并且适用于面向无连接的协议,如 UDP(用户数据报协议)。recvfrom
允许程序接收数据同时获取数据发送方的地址信息。
以下是 recvfrom
函数的原型:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
参数解释:
sockfd
: 这是已经创建并绑定的套接字的文件描述符。buf
: 这是一个指向缓冲区的指针,用于存储接收到的数据。len
: 这是缓冲区buf
的大小,以字节为单位。flags
: 这是一些标志位,用于修改recvfrom
的行为。例如,MSG_DONTWAIT
表示非阻塞模式,MSG_WAITALL
表示等待直到接收到指定长度的数据。src_addr
: 这是一个指向sockaddr
结构体的指针,用于存储发送方的地址信息。如果不需要获取发送方的地址,可以设置为NULL
。addrlen
: 这是一个指向整型的指针,用于指定src_addr
结构体的大小。在调用recvfrom
之前,应该将其设置为src_addr
结构体的大小,在调用之后,它将被设置为新接收到的地址的实际大小。
返回值:- 如果成功,
recvfrom
返回接收到的字节数。 - 如果连接被对方优雅地关闭,返回 0。
- 如果发生错误,返回 -1,并设置全局变量
errno
来指示错误的原因。
使用recvfrom
时,需要处理可能出现的各种错误情况,例如,如果套接字处于非阻塞模式并且没有数据可读,recvfrom
可能会返回EAGAIN
或EWOULDBLOCK
错误。
示例代码:
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int sockfd;
struct sockaddr_in server_addr, client_addr;
socklen_t addrlen = sizeof(client_addr);
char buffer[1024];
ssize_t recv_len;
// 创建套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
// 绑定套接字到地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(12345);
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 接收数据
recv_len = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &addrlen);
if (recv_len < 0) {
perror("recvfrom failed");
exit(EXIT_FAILURE);
}
// 处理接收到的数据
printf("Received message: %s\n", buffer);
// 关闭套接字
close(sockfd);
return 0;
}
在这个示例中,我们创建了一个 UDP 套接字,将其绑定到一个端口,然后使用 recvfrom
接收数据。我们打印出接收到的消息,然后关闭套接字。