内核中的UDP socket流程(7)——udp_sendmsg

简介: 作者:gfree.wind@gmail.com原文:http://blog.chinaunix.net/space.php?uid=23629988&do=blog&id=85925sock_sendmsg的代码很简单int sock_sendmsg(struct sock...
作者:gfree.wind@gmail.com

sock_sendmsg的代码很简单
  1. int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
  2. {
  3.      struct kiocb iocb;
  4.      struct sock_iocb siocb;
  5.      int ret;

  6.      init_sync_kiocb(&iocb, NULL);
  7.      iocb.private = &siocb;
  8.      ret = __sock_sendmsg(&iocb, sock, msg, size);
  9.      if (-EIOCBQUEUED == ret)
  10.           ret = wait_on_sync_kiocb(&iocb);
  11.      return ret;
  12. }
首先定义了一个struct kiocb类型的iocb——linux内核中所有I/O操作都要依赖于合格结构,然后初始化它。然后调用__sock_sendmsg,而__sock_sendmsg又调用UDP的sendmsg去做真正的发送。
也就是说,对于UDP的socket来说,sendto调用,真正去做工作的是udp_sendmsg这个函数。
  1. int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
  2.           size_t len)
  3. {
  4.      struct inet_sock *inet = inet_sk(sk);
  5.      struct udp_sock *up = udp_sk(sk);
  6.      int ulen = len;
  7.      struct ipcm_cookie ipc;
  8.      struct rtable *rt = NULL;
  9.      int free = 0;
  10.      int connected = 0;
  11.      __be32 daddr, faddr, saddr;
  12.      __be16 dport;
  13.      u8 tos;
  14.      int err, is_udplite = IS_UDPLITE(sk);
  15.      int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
  16.      int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
将sk转为udp内部使用的类型指针,在TCP/IP中充斥了这样的转换。主要原因是因为对于上层来说,需要一个统一的类型,而到了底层的具体实现时,都会将上层抽象的数据类型,转为自己所需的类型。
并判断该UDP是否是udplite——udplite的定义见http://en.wikipedia.org/wiki/UDP_Lite
  1.      if (len > 0xFFFF)
  2.           return -EMSGSIZE;

  3.      /*
  4.      * Check the flags.
  5.      */

  6.      if (msg->msg_flags & MSG_OOB) /* Mirror BSD error message compatibility */
  7.           return -EOPNOTSUPP;
进行一些错误检测。
  1.      ipc.opt = NULL;
  2.      ipc.shtx.flags = 0;

  3.      if (up->pending) {
  4.           /*
  5.           * There are pending frames.
  6.           * The socket lock must be held while it's corked.
  7.           */
  8.           lock_sock(sk);
  9.           if (likely(up->pending)) {
  10.                if (unlikely(up->pending != AF_INET)) {
  11.                     release_sock(sk);
  12.                     return -EINVAL;
  13.                }
  14.                goto do_append_data;
  15.           }
  16.           release_sock(sk);
  17.      }
  18.      ulen += sizeof(struct udphdr);
如果该socket有pending的frame,那么直接将数据追加。如果没有就ulen加上udp首部的长度。
  1.      /*
  2.      * Get and verify the address.
  3.      */
  4.      if (msg->msg_name) {
  5.           struct sockaddr_in * usin = (struct sockaddr_in *)msg->msg_name;
  6.           if (msg->msg_namelen sizeof(*usin))
  7.                return -EINVAL;
  8.           if (usin->sin_family != AF_INET) {
  9.                if (usin->sin_family != AF_UNSPEC)
  10.                     return -EAFNOSUPPORT;
  11.           }

  12.           daddr = usin->sin_addr.s_addr;
  13.           dport = usin->sin_port;
  14.           if (dport == 0)
  15.                return -EINVAL;
  16.      } else {
  17.           if (sk->sk_state != TCP_ESTABLISHED)
  18.                return -EDESTADDRREQ;
  19.           daddr = inet->inet_daddr;
  20.           dport = inet->inet_dport;
  21.           /* Open fast path for connected socket.
  22.              Route will not be used, if at least one option is set.
  23.           */
  24.           connected = 1;
  25.      }
  26.      ipc.addr = inet->inet_saddr;
如果msg->msg_name不为空,就说明指定了目的地址,对其进行检验。如果为空,就就需要对sock的状态进行检验,查看其是否是连接状态——UDP的socket同样是可以调用connect,这样就不需要每次都指定发送地址了。

今天有点困了,就这样了。



目录
相关文章
|
6天前
|
存储 Python
Python网络编程基础(Socket编程) UDP 发送和接收数据
【4月更文挑战第10天】对于UDP客户端而言,发送数据是一个相对简单的过程。首先,你需要构建一个要发送的数据报,这通常是一个字节串(bytes)。然后,你可以调用socket对象的`sendto`方法,将数据报发送到指定的服务器地址和端口。
|
6天前
|
存储 Python
Python网络编程基础(Socket编程)UDP客户端编程
【4月更文挑战第9天】在UDP通信中,客户端负责发送数据到服务器,并接收来自服务器的响应。与服务器不同,客户端通常不需要绑定到特定的地址和端口,因为它可以临时使用任何可用的端口来发送数据。下面,我们将详细讲解UDP客户端编程的基本步骤。
|
6天前
|
网络协议 Python
Python网络编程基础(Socket编程)创建UDP socket对象
【4月更文挑战第8天】在Python中创建UDP服务器涉及使用`socket`模块创建socket对象,如`udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)`,然后绑定到特定IP地址和端口,如`udp_socket.bind(('localhost', 12345))`。服务器通过`recvfrom`在无限循环中监听和接收数据报。这只是基础,实际应用还需处理接收、解析、响应及错误处理等。接下来可学习如何利用socket对象进行数据交互以构建完整服务器。
|
6天前
|
网络协议 网络性能优化 开发者
Python网络编程基础(Socket编程)UDP Socket编程
【4月更文挑战第8天】Python网络编程中,UDP与TCP协议各有特点。TCP提供可靠连接,确保数据顺序与完整性,适合文件传输等;UDP则无连接,速度快,常用于实时音视频,牺牲了数据可靠性。Python的socket库支持两者,开发者可根据需求选择。
|
9月前
|
网络协议 Linux C语言
linux下CC++网络编程基本:socket实现tcp和udp的例子
linux下CC++网络编程基本:socket实现tcp和udp的例子
172 0
|
7月前
|
安全 网络协议 Java
Thread类的用法 && 线程安全 && 多线程代码案例 && 文件操作和 IO && 网络原理初识 &&UDP socket
Thread类的用法 && 线程安全 && 多线程代码案例 && 文件操作和 IO && 网络原理初识 &&UDP socket
42 0
|
6天前
|
算法 Linux 调度
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
48 1
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
|
6天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
6天前
|
Python
Python网络编程基础(Socket编程)UDP服务器编程
【4月更文挑战第8天】Python UDP服务器编程使用socket库创建UDP套接字,绑定到特定地址(如localhost:8000),通过`recvfrom`接收客户端数据报,显示数据长度、地址和内容。无连接的UDP协议使得服务器无法主动发送数据,通常需应用层实现请求-响应机制。当完成时,用`close`关闭套接字。
|
6天前
|
网络协议 Linux
TCP 和 UDP 的 Socket 调用
【2月更文挑战第19天】
TCP 和 UDP 的 Socket 调用