大家好,欢迎来到IT知识分享网。
recvfrom()
recvfrom()
函数是一个系统调用,用于从套接字接收数据。该函数通常与无连接的数据报服务(如 UDP)一起使用,但也可以与其他类型的套接字使用。与简单的 recv()
函数不同,recvfrom()
可以返回数据来源的地址信息。
函数原型为:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
参数解释:
- sockfd:一个已打开的套接字的描述符。
- buf:一个指针,指向用于存放接收到的数据的缓冲区。
- len:缓冲区的大小(以字节为单位)。
- flags:控制接收行为的标志。通常可以设置为0,但以下是一些可用的标志:
MSG_WAITALL
:尝试接收全部请求的数据。函数可能会阻塞,直到收到所有数据。MSG_PEEK
:查看即将接收的数据,但不从套接字缓冲区中删除它【1】。- 其他一些标志还可以影响函数的行为,但在大多数常规应用中很少使用。
- src_addr:一个指针,指向一个
sockaddr
结构,用于保存发送数据的源地址。 - addrlen:一个值-结果参数。开始时,它应该设置为
src_addr
缓冲区的大小。当recvfrom()
返回时,该值会被修改为实际地址的长度(以字节为单位)。
返回值:
- 在成功的情况下,
recvfrom()
返回接收到的字节数。 - 如果没有数据可读或套接字已经关闭,那么返回值为0。
- 出错时,返回
-1
,并设置全局变量errno
以指示错误类型。
例子:
struct sockaddr_in sender; socklen_t sender_len = sizeof(sender); char buffer[1024]; int bytes_received = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&sender, &sender_len); if (bytes_received < 0) {
perror("recvfrom failed"); // handle error }
在这个例子中,我们使用 recvfrom()
从套接字 sockfd
接收数据。发送者的地址和端口信息保存在 sender
结构中。
sendto()
sendto()
函数是一个系统调用,用于发送数据到一个指定的地址。它经常与无连接的数据报协议,如UDP,一起使用。不像 send()
函数只能发送数据到一个预先建立连接的远端,sendto()
允许在每次发送操作时指定目的地址。
函数原型为:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
参数解释:
- sockfd:一个已打开的套接字的描述符。
- buf:一个指针,指向要发送的数据的缓冲区。
- len:要发送的数据的大小(以字节为单位)。
- flags:控制发送行为的标志。通常可以设置为0。一些可用的标志包括:
MSG_CONFIRM
:在数据报协议下告诉网络层该数据已经被确认。MSG_DONTROUTE
:不查找路由,数据报将只发送到本地网络。- 其他标志可以影响函数的行为,但在大多数常规应用中很少使用。
- dest_addr:指向
sockaddr
结构的指针,该结构包含目标地址和端口信息。 - addrlen:
dest_addr
缓冲区的大小(以字节为单位)。
返回值:
- 成功时,
sendto()
返回实际发送的字节数。 - 出错时,返回
-1
并设置全局变量errno
以指示错误类型。
例子:
struct sockaddr_in receiver; receiver.sin_family = AF_INET; receiver.sin_port = htons(12345); // Some port number inet_pton(AF_INET, "192.168.1.1", &receiver.sin_addr); // Some IP address char message[] = "Hello, World!"; ssize_t bytes_sent = sendto(sockfd, message, sizeof(message), 0, (struct sockaddr*)&receiver, sizeof(receiver)); if (bytes_sent < 0) {
perror("sendto failed"); // handle error }
在这个例子中,我们使用 sendto()
发送一个字符串到指定的IP地址和端口号。如果发送失败,我们打印一个错误消息。
注1:
让我们通过一个简单的示例来展示如何使用MSG_PEEK
标志来窥探套接字中的数据。
假设场景:我们正在编写一个简单的TCP服务器,该服务器接收客户端发送的消息。这些消息由一个头部开始,表示随后的数据长度。我们希望窥探这个头部,以便知道接下来应该读取多少数据。
假设消息头部长度固定为4字节,表示数据的长度。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #define PORT 8080 #define HEADER_SIZE 4 int main() {
int server_socket, client_socket; struct sockaddr_in address; int addr_len = sizeof(address); char buffer[1024]; // 创建TCP套接字 server_socket = socket(AF_INET, SOCK_STREAM, 0); if (server_socket == -1) {
perror("socket creation failed"); exit(EXIT_FAILURE); } // 绑定套接字到指定的端口 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); if (bind(server_socket, (struct sockaddr*)&address, sizeof(address)) == -1) {
perror("bind failed"); close(server_socket); exit(EXIT_FAILURE); } // 开始监听 if (listen(server_socket, 3) == -1) {
perror("listen failed"); close(server_socket); exit(EXIT_FAILURE); } printf("Waiting for a connection...\n"); client_socket = accept(server_socket, (struct sockaddr*)&address, (socklen_t*)&addr_len); if (client_socket == -1) {
perror("accept failed"); close(server_socket); exit(EXIT_FAILURE); } printf("Connection established.\n"); // 窥探消息头部 int peek_len = recv(client_socket, buffer, HEADER_SIZE, MSG_PEEK); if (peek_len != HEADER_SIZE) {
printf("Failed to peek header\n"); close(client_socket); close(server_socket); exit(EXIT_FAILURE); } // 假设头部数据是一个整数,表示接下来的消息长度 int message_len = *((int*)buffer); printf("Expected message length: %d\n", message_len); // 现在,可以根据消息长度读取整个消息 close(client_socket); close(server_socket); return 0; }
这只是一个简化的示例,实际应用中还需要考虑其他方面,如错误处理、多个客户端的处理、消息头和数据的解析等。
【1】若想了解sockaddr_in结构体,可移步到
Linux网络编程- sockaddr & sockaddr_in & in_addr
【2】若想了解常用的网络编程函数,可移步到
Linux- 网络编程初探
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121691.html