一、格式
  • 这两个函数一般适用于UDP使用
#include<sys/types.h>
#include<sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t nbytes,  int flags, 
                struct sockaddr *from, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t nbytes, int flags, 
                const struct sockaddr *to, socklen_t addrlen);

参数

  • 参数1:套接字描述符
  • 参数2、3:发送/接收数据的缓冲区指针和读写的字节数
  • 参数4:与recv/send/recvmsg/sendmsg函数的相同(见文章:javascript:void(0)javascript:void(0))。不想使用就设置为0
  • 参数5、6:发送/接收数据的套接字地址、以及地址大小

recvfrom返回值

  • 成功:返回接收到的字节数
  • 返回0:
    • 当一个流套接字对等节点有序地关闭时,返回值将为0(传统的“end-of-file”标志)
    • 不同域(例如UNIX和Internet域)中的数据报套接字允许零长度的数据报。当接收到这样的数据报时,返回值为0。
    • 如果要从流套接字接收的请求字节数为0,也可以返回值0
  • 失败:返回-1,并将errno设置为如下的值:
    • 这些是套接字层生成的一些标准错误。底层协议模块可能会产生和返回其他错误
    • EAGAIN或EWOULDBLOCK:套接字标记为非阻塞,接收操作将阻塞,或者设置了接收超时,并且在接收数据之前超时已经过期。在这种情况下,POSIX.1允许返回任何一个错误,并且不要求这些常量具有相同的值,因此可移植应用程序应该检查这两种可能性
    •  EBADF:参数sockfd是一个无效的文件描述符
    • ECONNREFUSED:远程主机拒绝允许网络连接(通常是因为它没有运行所请求的服务)
    • EFAULT:将接收缓冲区指针指向进程地址空间之外
    • EINTR :在任何数据可用之前,接收被信号的发送打断
    • EINVAL:无效参数传递
    • ENOMEM:无法为recvmsg()分配内存
    • ENOTCONN:套接字与一个面向连接的协议相关联,并且还没有被连接(参阅connect()和accept())
    • ENOTSOCK:文件描述符sockfd不引用套接字

sendto返回值

  • 成功:返回发送的字节数
  • 失败:返回-1,并将errno设置为如下的值:
    • 这些是套接字层产生的一些标准错误。底层协议模块可能会产生和返回其他错误
    • EACCES:
      • 在目标套接字文件上拒绝EACCES(对于UNIX域套接字,它是由路径名标识的)的写权限,或者拒绝路径前缀中的某个目录的搜索权限。(参阅path_resolution())。
      • (对于UDP套接字)尝试发送到网络/广播地址,就好像它是一个单播地址
    • EAGAIN或EWOULDBLOCK:套接字标记为非阻塞,请求的操作将阻塞。在这种情况下,POSIX.1-2001允许返回任何一个错误,并且不要求这些常量具有相同的值,因此可移植应用程序应该检查这两种可能性
    • EAGAIN:sockfd引用的套接字以前没有绑定到一个地址,当尝试将其绑定到临时端口时,确定临时端口范围内的所有端口号目前都在使用。参见ip(7)中的/proc/sys/net/ipv4/ip_local_port_range的讨论
    • EALREADY:另一个快速开放正在进行中
    • EBADF:sockfd不是一个有效的打开文件描述符
    • ECONNRESET:通过对等点重置连接
    • EDESTADDRREQ:套接字不是连接模式,没有设置对等地址
    • EFAULT:为参数指定了无效的用户空间地址
    • EINTR:在任何数据传输之前发生的信号
    • EINVAL:无效参数传递
    • EISCONN:连接模式套接字已经连接,但是指定了一个接收方。(现在要么返回此错误,要么忽略收件人规范。)
    • EMSGSIZE:套接字类型要求以原子方式发送消息,而要发送的消息的大小使得这种情况不可能发生
    • ENOBUFS:网络接口的输出队列已满。这通常表示接口已停止发送,但可能是由瞬态拥塞引起的。(通常,这在Linux中不会发生。当设备队列溢出时,数据包会无声地丢弃。)
    • ENOMEM:没有可用的内存
    • ENOTCONN:套接字没有连接,并且没有给定目标
    • ENOTSOCK:文件描述符sockfd不引用套接字
    • EOPNOTSUPP:标志参数中的一些位不适合套接字类型
    • EPIPE:在一个面向连接的套接字上,本地端已经关闭。在本例中,除非设置了MSG_NOSIGNAL,否则进程还将收到一个SIGPIPE

注意事项

  • 最后一个参数recvfrom函数为地址大小指针,sendto函数为地址大小
  • 如果recvfrom的from参数是一个空指针,那么相应的长度参数(addrlen)也必须是一个空指针表示我们并不关心数据发送者的协议地址
二、注意事项
  • ①写一个长度为0的数据报是可行的在UDP情况下,这会形成一个只包含一个IP首部(对于 IPv4通常为20个字节,对于IPv6通常为40个字节)和一个8字节UDP首部而没有数据的IP数据报。 这也意味着对于数据报协议,recvfrom返回0值是可接受的:它并不像TCP套接字上read返回0 值那样表示对端已关闭连接。既然UDP是无连接的,因此也就没有诸如关闭一个UDP连接之类事情
  • ②recvfrom和sendto都可以用于TCP,尽管通常没有理由这样做