zoukankan      html  css  js  c++  java
  • recv, recvfrom, recvmsg

    recv,recvfrom,recvmsg函数用于从套接字接收信息。
    ssize_t recv (int s, void *buf, size_t len, int flags);

    ssize_t recvfrom (int s, void * restrict buf, size_t len, int flags,
    struct sockaddr * restrict from, socklen_t * restrict fromlen);

    ssize_t recvmsg (int s, struct msghdr *msg, int flags);

    recvfrom和recvmsg系统调用用于从套接字接收消息,也可以用来接受套接字数据,不管其是否是面向连接的。 recv函数通常用于面向连接的套接字(参看[[[Open C 套接字: connect 方法|connect]]),等同于用空指针传入from参数时

    的recvfrom。所有三个例程都返回成功时的消息长度。

    recvmsg系统调用使用msghdr结构将直接提供的参数个数减到最少,这个结构具有以下格式,定义在sys/socket.h文件:
    struct msghdr {
    caddr_t msg_name; /* optional address */
    u_int msg_namelen; /* size of address */
    struct iovec *msg_iov; /* scatter/gather array */
    u_int msg_iovlen; /* # elements in msg_iov */
    caddr_t msg_control; /* ancillary data, see below */
    u_int msg_controllen; /* ancillary data buffer len */
    int msg_flags; /* flags on received message */
    };

    下面的代码片段演示了recv, recvfrom, recvmsg函数的用法:
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <unistd.h>
    void Recv()
    {
    struct sockaddr_in serv_addr;
    int sock_fd;
    char line[10];
    int size = 10;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    serv_addr.sin_port = htons(5000);
    sock_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    connect(sock_fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
    recv(sock_fd, line, size, 0);
    close(sock_fd);
    }


    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <unistd.h>
    void Sendto()
    {
    struct sockaddr_in sender_addr;
    int sock_fd;
    char line[15] = "Hello World!";
    unsigned int size = sizeof(sender_addr);
    sock_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    sender_addr.sin_family = AF_INET;
    sender_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    sender_addr.sin_port = htons(5000);
    recvfrom(sock_fd,line,13,0,(struct sockaddr*)&sender_addr,&size);
    close(sock_fd);
    }


    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <unistd.h>
    void SendMsgRecvMsg()
    {
    int sock_fd;
    unsigned int sender_len;
    struct msghdr msg;
    struct iovec iov;
    struct sockaddr_in receiver_addr,sender_addr;
    char line[10];
    sock_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    receiver_addr.sin_family = AF_INET;
    receiver_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    receiver_addr.sin_port = htons(5000);
    bind(sock_fd,(struct sockaddr*)&receiver_addr,sizeof(receiver_addr));
    sender_len = sizeof(sender_addr);
    msg.msg_name = &sender_addr;
    msg.msg_namelen = sender_len;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_iov->iov_base = line;
    msg.msg_iov->iov_len = 10;
    msg.msg_control = 0;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;
    recvmsg(sock_fd,&msg,0);
    close(sock_fd);
    }

    这些调用返回接收的字节数,或者如错误发生返回-1。









    ==========================================================================================
    【recv/recvfrom/recvmsg系统调用】
    功能描述:
    从套接字上接收一个消息。对于recvfrom 和 recvmsg,可同时应用于面向连接的和无连接的套接字。recv一般只用在面向连接的套接字,几乎等同于recvfrom,只要将recvfrom的第五个参数设置NULL。
    如果消息太大,无法完整存放在所提供的缓冲区,根据不同的套接字,多余的字节会丢弃。
    假如套接字上没有消息可以读取,除了套接字已被设置为非阻塞模式,否则接收调用会等待消息的到来。

    用法:
    #include <sys/types.h>
    #include <sys/socket.h>
    ssize_t recv(int sock, void *buf, size_t len, int flags);
    ssize_t recvfrom(int sock, void *buf, size_t len, int flags,
    struct sockaddr *from, socklen_t *fromlen);
    ssize_t recvmsg(int sock, struct msghdr *msg, int flags);
    参数:
    sock:索引将要从其接收数据的套接字。
    buf:存放消息接收后的缓冲区。
    len:buf所指缓冲区的容量。
    flags:是以下一个或者多个标志的组合体,可通过or操作连在一起
    MSG_DONTWAIT:操作不会被阻塞。
    MSG_ERRQUEUE: 指示应该从套接字的错误队列上接收错误值,依据不同的协议,错误值以某种辅佐性消息的方式传递进来, 使用者应该提供足够大的缓冲区。导致错误的原封包通过msg_iovec作为一般的数据来传递。导致错误的数据报原目标地址作为msg_name被提供。 错误以sock_extended_err结构形态被使用,定义如下
    #define SO_EE_ORIGIN_NONE 0
    #define SO_EE_ORIGIN_LOCAL 1
    #define SO_EE_ORIGIN_ICMP 2
    #define SO_EE_ORIGIN_ICMP6 3
    struct sock_extended_err
    {
    u_int32_t ee_errno; /* error number */
    u_int8_t ee_origin; /* where the error originated */
    u_int8_t ee_type; /* type */
    u_int8_t ee_code; /* code */
    u_int8_t ee_pad;
    u_int32_t ee_info; /* additional information */
    u_int32_t ee_data; /* other data */
    /* More data may follow */
    };
    MSG_PEEK:指示数据接收后,在接收队列中保留原数据,不将其删除,随后的读操作还可以接收相同的数据。
    MSG_TRUNC:返回封包的实际长度,即使它比所提供的缓冲区更长, 只对packet套接字有效。
    MSG_WAITALL:要求阻塞操作,直到请求得到完整的满足。然而,如果捕捉到信号,错误或者连接断开发生,或者下次被接收的数据类型不同,仍会返回少于请求量的数据。
    MSG_EOR:指示记录的结束,返回的数据完成一个记录。
    MSG_TRUNC:指明数据报尾部数据已被丢弃,因为它比所提供的缓冲区需要更多的空间。
    MSG_CTRUNC:指明由于缓冲区空间不足,一些控制数据已被丢弃。
    MSG_OOB:指示接收到out-of-band数据(即需要优先处理的数据)。
    MSG_ERRQUEUE:指示除了来自套接字错误队列的错误外,没有接收到其它数据。
    from:指向存放对端地址的区域,如果为NULL,不储存对端地址。
    fromlen:作为入口参数,指向存放表示from最大容量的内存单元。作为出口参数,指向存放表示from实际长度的内存单元。
    msg:指向存放进入消息头的内存缓冲,结构形态如下
    struct msghdr {
    void *msg_name; /* optional address */
    socklen_t msg_namelen; /* size of address */
    struct iovec *msg_iov; /* scatter/gather array */
    size_t msg_iovlen; /* # elements in msg_iov */
    void *msg_control; /* ancillary data, see below */
    socklen_t msg_controllen; /* ancillary data buffer len */
    int msg_flags; /* flags on received message */
    };

    可能用到的数据结构有
    struct cmsghdr {
    socklen_t cmsg_len; /* data byte count, including hdr */
    int cmsg_level; /* originating protocol */
    int cmsg_type; /* protocol-specific type */
    /* followed by
    u_char cmsg_data[]; */
    };

    返回说明:
    成功执行时,返回接收到的字节数。另一端已关闭则返回0。失败返回-1,errno被设为以下的某个值
    EAGAIN:套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
    EBADF:sock不是有效的描述词
    ECONNREFUSE:远程主机阻绝网络连接
    EFAULT:内存空间访问出错
    EINTR:操作被信号中断
    EINVAL:参数无效
    ENOMEM:内存不足
    ENOTCONN:与面向连接关联的套接字尚未被连接上
    ENOTSOCK:sock索引的不是套接字

  • 相关阅读:
    安利一波这12个IDEA插件,太香了!
    作为Java新手,如何才能快速的看透一个Java项目?
    为什么放弃Hibernate、JPA、Mybatis,最终选择JDBCTemplate
    为什么 ConcurrentHashMap 的读操作不需要加锁?
    MySQL索引的使用是怎么样的?5个点轻松掌握!
    掌握MyBatis插件原理轻松写出自己的PageHelper分页插件
    Spring中BeanFactory与FactoryBean到底有什么区别?
    MongoDB学习笔记(一)——Windows 下安装MongoDB
    ASP.Net WebAPI中添加helppage帮助页面
    C#代码实现在控制台输入密码显示星号
  • 原文地址:https://www.cnblogs.com/hnrainll/p/2141480.html
Copyright © 2011-2022 走看看