recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);/函数简单了解

来源:互联网 发布:php表格代码 编辑:程序博客网 时间:2024/04/30 09:02

#include <sys/types.h>
#include <sys/socket.h>

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

第1个参数s代表正在监听的端口的套接口文件描述符,它是由函数socket()生成的

第2个参数buff表示接收数据缓冲区, 接收到的数据将放在这个指针所指向的内存空间中

第3个参数len表示接收数据缓冲区大小,系统根据这个值来确保接收缓冲区的安全,防止溢出

第4个参数from是指向本地的数据结构sockaddr_in 的指针,发送数据时发送方的地址信息放在这个结构中

第5个参数fromlen表示第4个参数的所指内容的长度,可以使用sizeof(struct sockaddr_in)来获得。

当函数陷入内核中时,执行long sys_recvfrom(int fd, , void __user *ubuf, size_t size, int __user*addr_len)

系统调用函数sys_recvfrom主要查找文件描述符对应的内核socket结构,建立一个消息结构,将用户空间的地址缓冲区指针和数据缓冲区指针打包到消息队列中,在套接字文件描述符对应的数据链中查找对应的数据,将数据复制到消息中,销毁数据链中的数据,将数据复制到应用层的空间中, 减少文件描述符的引用计数。

sys_recvfrom()调用函数 sockfd_lookup_light() 查找到文件描述符对应的内核,socket结构后,会申请一块内存空间来保存链接成功的客户端状态,socket结构的一些参数,例如类型type操作方式ops等会继承服务器原来的值,例如原来服务器的类型为AF——INET则其操作模式仍然为af_inet.c文件中的各个函数,然后会查找到文件描述符表,获得一个新的结构对应的文件描述符。

在内核中使用一个消息结构msghdr用来存放所有的数据结构,其原型如下:

struct  msghdr{

       void *msg_name; //socket名称

      int msg_namelen; //socket名称的长度

       struct iovec* msg_iov; //向量,存放数据

       __kernel_size_t msg_iovlen;//向量数量

      void *msg_control;

      __kernel_size_t msg_controllen;//msg_control的数量

      unsigned msg_flags;      //消息选项

};

对于AF——INET 族,recvfrom对应于udp_recvmsg()函数,其实现在文件af_inet.c 中,

1接收数据报数据,。在接收的时候根据设置超时来确定是否要一直等待。

2计算复制出的数据长度,当街收到的数据长度比用户缓冲区的长度大时。设置MSG——MSG_TRUNC标志方便下次的复制

3将数据复制到用户缓冲区空间中。

4复制发送方的地址和协议族

5根据消息结构的标志设置,接收其他的信息,

6销毁数据报缓冲区对应的变量。

1 0
原创粉丝点击