POSIX 网络编程问题

354 天前
 0littleboy

能否给个 send 和 recv 的例子

要求能处理常见的 errno ,如:EAGAIN, EINTR

当接受到的数据大小 n > BUF_SIZE 时,能够正确处理

862 次点击
所在节点    C
1 条回复
ohwind
354 天前
By ChatGPT:
下面是一个使用 POSIX 网络编程的 send() 和 recv() 函数的例子,可以处理常见的错误和当接受到的数据大小大于缓冲区大小时的情况:
```
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

#define BUF_SIZE 1024

void handle_error(const char *msg) {
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(EXIT_FAILURE);
}

void send_data(int sockfd, const char *data, size_t len) {
size_t total_sent = 0;
while (total_sent < len) {
ssize_t n = send(sockfd, data + total_sent, len - total_sent, 0);
if (n < 0) {
if (errno == EAGAIN || errno == EINTR) {
continue;
} else {
handle_error("send error");
}
}
total_sent += n;
}
}

void recv_data(int sockfd) {
char buf[BUF_SIZE];
ssize_t n;
while ((n = recv(sockfd, buf, sizeof(buf), 0)) > 0) {
// handle received data
if (n > BUF_SIZE) {
fprintf(stderr, "received data too large: %zd\n", n);
exit(EXIT_FAILURE);
}
}
if (n < 0) {
if (errno == EAGAIN || errno == EINTR) {
// try again later
return;
} else {
handle_error("recv error");
}
}
// n == 0 means the other end closed the connection
printf("connection closed by peer\n");
exit(EXIT_SUCCESS);
}
```
在 send_data() 函数中,我们使用一个循环来确保将所有数据都发送出去。如果 send() 函数返回一个负值,我们首先检查错误码是否为 EAGAIN 或 EINTR ,如果是,则继续循环以重新尝试发送数据。否则,我们假定出现了其他错误并调用 handle_error() 函数来处理它。

在 recv_data() 函数中,我们使用一个循环来反复接收数据,直到 recv() 函数返回一个小于或等于零的值,这表示连接已关闭或出现错误。如果 recv() 函数返回一个负值,我们首先检查错误码是否为 EAGAIN 或 EINTR ,如果是,则说明暂时无法接收数据,可以稍后再尝试。如果出现其他错误,则调用 handle_error() 函数处理它。如果接收到的数据的大小大于缓冲区大小,则输出错误消息并退出程序。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/938518

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX