开发者社区> nothingfinal> 正文

TCP/IP源码(22)——tcp_sendmsg(1)

简介: 本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。 作者:gfree.
+关注继续查看
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
    


今天开始学习tcp_sendmsg
  1. int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
  2.         size_t size)
  3. {
  4.     struct iovec *iov;
  5.     /*
  6.     从通用的struct sock *sk得到struct tcp_sock *tp
  7.     其实只是一个强制类型转换,因为strcut sock为所有其它socket类型的第一个成员,所有可以直接对指针进行     强制类型转换
  8.     */
  9.     struct tcp_sock *tp = tcp_sk(sk);
  10.     struct sk_buff *skb;
  11.     int iovlen, flags;
  12.     int mss_now, size_goal;
  13.     int sg, err, copied;
  14.     long timeo;

  15.     lock_sock(sk);
  16.     TCP_CHECK_TIMER(sk);

  17.     flags = msg->msg_flags;
  18.     /* 
  19.        设置发送等待时间,如果设置了DONTWAIT,则timeo为0. 
  20.        如果没有该标志,则timeo就为sock->sk_sndtimeo
  21.        */
  22.     timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);

  23.     /* Wait for a connection to finish. */
  24.     /* 等到直到连接完成 */
  25.     if ((1 sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
  26.         if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)
  27.             goto out_err;

  28.     /* This should be in poll */
  29.     clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
     /* 计算当前的MSS, size_goal为可发送数据的大小 */
  1.     mss_now = tcp_send_mss(sk, &size_goal, flags);

  2.     /* Ok commence sending. */
  3.     iovlen = msg->msg_iovlen;
  4.     iov = msg->msg_iov;
  5.     copied = 0;

  6.     err = -EPIPE;
  7.     if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
  8.         goto out_err;

  9.     sg = sk->sk_route_caps & NETIF_F_SG;
     /* 开始发送数据 */
  1.     while (--iovlen >= 0) {
  2.         size_t seglen = iov->iov_len;
  3.         unsigned char __user *from = iov->iov_base;

  4.         iov++;

  5.         while (seglen > 0) {
  6.             int copy = 0;
  7.             int max = size_goal;

  8.             skb = tcp_write_queue_tail(sk);
  9.             /* 计算需要复制的字节数为copy */
  10.             if (tcp_send_head(sk)) {
  11.                 if (skb->ip_summed == CHECKSUM_NONE)
  12.                     max = mss_now;
  13.                 copy = max - skb->len;
  14.             }

  15.             if (copy = 0) {
  16.                 /* 已复制完以前的数据了 */
  17. new_segment:
  18.                 /* Allocate new segment. If the interface is SG,
  19.                  * allocate skb fitting to single page.
  20.                  */
                    /* 检验是否还有空闲send buffer,若没有则跳到wait_for_sndbuf */
  21.                 if (!sk_stream_memory_free(sk))
  22.                     goto wait_for_sndbuf;
                 /* 申请新的skb buffer */
  1.                 skb = sk_stream_alloc_skb(sk,
  2.                              select_size(sk, sg),
  3.                              sk->sk_allocation);
  4.                 /* 若分配失败,则跳转到wait_for_memory */
  5.                 if (!skb)
  6.                     goto wait_for_memory;

  7.                 /*
  8.                  * Check whether we can use HW checksum.
  9.                  */
  10.                 if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
  11.                     skb->ip_summed = CHECKSUM_PARTIAL;
                 /* 将新分配的skb添加到sk上 */
  1.                 skb_entail(sk, skb);
  2.                 copy = size_goal;
  3.                 max = size_goal;
  4.             }
             /* 下面开始复制数据,未完待续 */

今天学习的代码不多,一方面是今天的空闲时间不多,家里有不少事情,另一方面,tcp的确实比较复杂。




版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
23523 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
14205 0
TCP/IP源码(59)——TCP中的三个接收队列
作者:gfree.wind@gmail.com 博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net  微博:weibo.com/glinuxer QQ技术群:4367710   本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。
644 0
TCP/IP源码(20)——数据包发送的流程图
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。 作者:gfree.wind@gmail.com 博客:linuxfocus.blog.chinaunix.net 今天,把之前看过的UDP发送的过程总结了一下,画出了数据包发送的流程图。
1063 0
TCP/IP源码(22)——tcp_sendmsg(1)
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。 作者:gfree.
1112 0
tcp/ip源码(18)——struct inet_sock中的cork用途
作者:gfree.wind@gmail.com 博客:linuxfocus.blog.chinaunix.net 在前面的学习过程中,遇到了位于struct inet_sock中的cork,当时没有把这个变量搞得很明白,没有完全搞清这个变量的用途。
1047 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
16589 0
+关注
nothingfinal
软件开发,安全加密
1069
文章
341
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载