射阳建设网站,正规货源网站大全,网站建设主流技术及效果,企业网页建设公司怎样收费recv 函数是在 Linux C 语言网络编程中用于从已连接的套接字接收数据的函数。它通常与 TCP 连接一起使用#xff0c;但也可以用于 UDP#xff08;尽管对于 UDP#xff0c;更常使用 recvfrom#xff0c;因为它还可以接收发送方的地址信息#xff09;。
函数原型
recv 函数…recv 函数是在 Linux C 语言网络编程中用于从已连接的套接字接收数据的函数。它通常与 TCP 连接一起使用但也可以用于 UDP尽管对于 UDP更常使用 recvfrom因为它还可以接收发送方的地址信息。
函数原型
recv 函数在 sys/socket.h 中定义其函数原型如下
#include sys/types.h
#include sys/socket.hssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数 sockfd 这是一个已打开的套接字描述符它标识了要从其接收数据的网络连接。对于 TCP这个套接字通常是通过 socket 函数创建的并且已经通过 connect 函数与远程服务器建立了连接或者通过 accept 函数接受了来自客户端的连接。 buf 这是一个指向缓冲区的指针该缓冲区用于存储从套接字接收到的数据。在调用 recv 函数之前应确保该缓冲区有足够的空间来存储要接收的数据。 len 这是缓冲区 buf 的长度以字节为单位。它指定了缓冲区中可以存储的最大数据量。 flags 这是一个整数值用于传递特殊的接收标志给底层协议。这些标志可以修改 recv 函数的行为。通常这个参数被设置为 0表示使用标准的接收行为。然而一些可能的标志包括 MSG_PEEK查看数据但不从套接字的接收队列中移除。MSG_WAITALL等待直到接收到完整的 len 字节数据或者发生错误。然而这个标志的行为可能因实现而异并且不建议在阻塞模式下使用。MSG_OOB仅接收带外数据out-of-band data。MSG_DONTWAIT非阻塞模式操作等效于使用非阻塞套接字。MSG_ERRQUEUE获取扩展的错误信息较少使用。
返回值
如果成功recv 函数返回实际接收到的字节数。这个数字可能小于 len 参数指定的长度这取决于发送方发送的数据量、套接字的接收缓冲区中的数据量以及网络条件。如果连接已正常关闭recv 函数返回 0。如果出现错误recv 函数返回 -1并设置全局变量 errno 以指示错误类型。
错误处理
当 recv 函数返回 -1 时可以检查 errno 来确定错误的原因。一些常见的错误包括
EWOULDBLOCK 或 EAGAIN套接字是非阻塞的并且没有数据可供立即接收。ECONNRESET连接被对端重置。ENOTCONN套接字未连接到远程地址。EINTR接收操作被中断通常是因为接收到了一个信号。EBADF提供的套接字描述符不是有效的或不支持接收操作。
注意事项 阻塞与非阻塞根据套接字的配置recv 函数可以表现为阻塞或非阻塞。在阻塞模式下recv 会等待直到有数据可以接收或发生错误。在非阻塞模式下如果没有数据可供接收recv 会立即返回 EWOULDBLOCK 或 EAGAIN 错误。 多次接收由于 TCP 的流性质一次 recv 调用可能不会接收到发送方发送的所有数据。因此可能需要多次调用 recv 来接收完整的消息或数据流。 数据边界recv 函数不保证按发送方发送的原始边界接收数据。应用程序需要自己处理消息的边界问题通常通过在消息前加上长度字段或使用特定的分隔符。 关闭连接当对端关闭连接时recv 函数将返回 0表示没有更多的数据可以接收。这是正常关闭连接的指示。 性能考虑与 send 类似频繁地接收小块数据可能不如一次性接收大块数据高效。应用程序应优化数据传输以提高性能。
在使用 recv 函数时应处理可能的错误和异常情况并确保正确地管理套接字和数据缓冲区。
示例代码
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include sys/socket.h
#include netinet/in.hint main() {// 假定 sockfd 是已经连接好的套接字int sockfd /* socket(...) */;// 用于存储接收数据的缓冲区char buffer[1024];// 清空缓冲区memset(buffer, 0, sizeof(buffer));// 接收数据int bytes_received recv(sockfd, buffer, sizeof(buffer), 0);if (bytes_received 0) {// 处理错误perror(recv failed);} else if (bytes_received 0) {// 对方已经关闭了连接printf(Peer has performed an orderly shutdown\n);} else {// 打印接收到的数据printf(Received (%d bytes): %.*s\n, bytes_received, bytes_received, buffer);}// 关闭套接字close(sockfd);return 0;
}
在上面的代码示例中sockfd 应已经是一个成功连接的 socket—这意味着在 TCP 的情况下应该在客户端使用 connect 或在服务器端使用 accept 来获得 sockfd。
在实际应用程序中通常会将 recv 放在某个循环中以持续接收数据。当 recv 返回 0 表示对方已经关闭了连接接收循环就应该结束。还需要处理各种可能出现的错误。
perror 函数是 C 语言中用来报告 errno 错误的常用方法。当系统调用或库函数出错时它们通常会设置全局变量 errno 来指示错误的类型。perror 函数可以读取当前的 errno 值并打印出一条描述该错误的消息到标准错误输出stderr。
perror 函数的原型如下
void perror(const char *str);
其中 str 是一个字符串指针它通常被用来提供关于出错上下文的额外信息。这个字符串会被打印出来后面紧跟着一个冒号、一个空格和由 errno 值对应的错误消息。
例如如果你调用了一个可能失败的函数如 open你可以立即调用 perror 来打印出任何发生的错误 #include stdio.h #include stdlib.h #include errno.h #include fcntl.h int main() { int fd open(nonexistent_file.txt, O_RDONLY); if (fd -1) { perror(Error opening file); return EXIT_FAILURE; } // ... 其他代码 ... return EXIT_SUCCESS; }
如果文件 nonexistent_file.txt 不存在open 函数会失败并设置 errno。然后 perror 会打印出类似以下的消息
Error opening file: No such file or directory
这里“Error opening file” 是传递给 perror 的字符串而 “No such file or directory” 是与 errno 值对应的系统错误消息。注意errno 的值在调用另一个可能设置 errno 的函数之前应当被认为是未定义的除非你明确地知道它不会被改变。因此通常在调用可能出错的函数之后立即检查 errno 并使用 perror 或其他方法来报告错误是一个好习惯。