网站免费注册会员怎么做,网站设计评价,大连网站建设金豆,本科电子商务专业就业方向目录
recvmsg 函数
函数原型
参数说明
返回值
sendmsg 函数
函数原型
参数说明
返回值
示例代码 recvmsg 和 sendmsg 是在 linux网络编程中用于通用数据读写的函数#xff0c;它们提供了比传统的 recv 和 send 函数更强大、灵活的功能#xff0c;特别是在处理复杂的…
目录
recvmsg 函数
函数原型
参数说明
返回值
sendmsg 函数
函数原型
参数说明
返回值
示例代码 recvmsg 和 sendmsg 是在 linux网络编程中用于通用数据读写的函数它们提供了比传统的 recv 和 send 函数更强大、灵活的功能特别是在处理复杂的套接字地址结构、控制消息和辅助数据时。
recvmsg 函数
函数原型
#include sys/socket.hssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
参数说明
sockfd套接字描述符标识接收数据的套接字。msg指向 struct msghdr 结构体的指针该结构体包含了接收数据的详细信息包括数据缓冲区、地址信息、控制消息等。struct msghdr 的定义通常如下其中关于struct iovec结构体以及相关知识请大家先看高级IO函数之readv和writev-CSDN博客
struct msghdr {void *msg_name; /* 指向套接字地址结构的指针 */socklen_t msg_namelen; /* 套接字地址结构的长度 */struct iovec *msg_iov; /* 指向iovec结构体数组的指针 */int msg_iovlen; /* iovec结构体数组的元素个数 */void *msg_control; /* 指向控制消息缓冲区的指针 */socklen_t msg_controllen; /* 控制消息缓冲区的长度 */int msg_flags; /* 接收消息的标志 */
};
flags接收数据时的标志位可以是 0 或以下一个或多个标志的按位或 MSG_DONTWAIT设置为非阻塞接收若没有数据可接收函数立即返回而不是阻塞等待。MSG_PEEK查看数据数据被复制到用户缓冲区但保留在套接字接收队列中下次接收操作仍可获取相同的数据。MSG_WAITALL等待直到请求的字节数全部被接收除非发生错误、接收到信号或连接被关闭。
返回值 成功时返回接收到的字节数。如果连接被关闭返回 0。出错时返回 -1并设置 errno 以指示错误原因如 EAGAIN非阻塞模式下无数据可读、EBADF无效的文件描述符等。
sendmsg 函数
函数原型
#include sys/socket.hssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
参数说明
sockfd套接字描述符标识发送数据的套接字。msg指向 struct msghdr 结构体的指针与 recvmsg 中的 msg 结构体类似但用于指定发送数据的相关信息如数据缓冲区、目标地址、控制消息等。flags发送数据时的标志位常见的标志包括 MSG_DONTWAIT设置为非阻塞发送若套接字缓冲区没有足够空间函数立即返回而不是阻塞等待。MSG_NOSIGNAL在面向连接的套接字如 TCP上发送数据时如果连接已断开不产生 SIGPIPE 信号而是返回 -1 并设置 errno 为 EPIPE。
返回值 成功时返回发送的字节数。出错时返回 -1并设置 errno 以指示错误原因如 EAGAIN非阻塞模式下套接字缓冲区满、EBADF无效的文件描述符等。
示例代码 大家可以类比udp服务器的逻辑去看。
#include stdio.h
#include stdlib.h
#include string.h
#include sys/socket.h
#include arpa/inet.h
#include unistd.h#define PORT 8080
#define BUFFER_SIZE 1024int main() {int sockfd;struct sockaddr_in servaddr, cliaddr;// 创建套接字sockfd socket(AF_INET, SOCK_DUDP, 0);if (sockfd 0) {perror(socket creation failed);exit(EXIT_FAILURE);}memset(servaddr, 0, sizeof(servaddr));memset(cliaddr, 0, sizeof(cliaddr));// 填充服务器地址结构servaddr.sin_family AF_INET;servaddr.sin_addr.s_addr INADDR_ANY;servaddr.sin_port htons(PORT);// 绑定套接字到指定地址和端口if (bind(sockfd, (const struct sockaddr *)servaddr, sizeof(servaddr)) 0) {perror(bind failed);close(sockfd);exit(EXIT_FAILURE);}char buffer[BUFFER_SIZE];struct msghdr send_msg, recv_msg;struct iovec iov_send, iov_recv;socklen_t len sizeof(cliaddr);// 初始化接收消息iov_recv.iov_base buffer;iov_recv.iov_len BUFFER_SIZE;recv_msg.msg_name (void *)cliaddr;recv_msg.msg_namelen sizeof(cliaddr);recv_msg.msg_iov iov_recv;recv_msg.msg_iovlen 1;recv_msg.msg_control NULL;recv_msg.msg_controllen 0;recv_msg.msg_flags 0;// 接收消息ssize_t recv_bytes recvmsg(sockfd, recv_msg, 0);if (recv_bytes 0) {perror(recvmsg failed);close(sockfd);exit(EXIT_FAILURE);}buffer[recv_bytes] \0;printf(Received: %s\n, buffer);// 初始化发送消息iov_send.iov_base Message received successfully;iov_send.iov_len strlen(Message received successfully);send_msg.msg_name (void *)cliaddr;send_msg.msg_namelen len;send_msg.msg_iov iov_send;send_msg.msg_iovlen 1;send_msg.msg_control NULL;send_msg.msg_controllen 0;send_msg.msg_flags 0;// 发送消息ssize_t send_bytes sendmsg(sockfd, send_msg, 0);if (send_bytes 0) {perror(sendmsg failed);close(sockfd);exit(EXIT_FAILURE);}printf(Sent %zd bytes\n, send_bytes);close(sockfd);return 0;
}