Chinaunix首页 | 论坛 | 博客
  • 博客访问: 154467
  • 博文数量: 41
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-14 10:16
文章分类
文章存档

2011年(1)

2010年(5)

2009年(35)

我的朋友

分类: LINUX

2009-10-09 10:43:29

2函数用途

向远端发送应答数据包并且更新窗口。

3调用关系

tcp_sendto/inet_send/inet_write

       |___tcp_write

4语句注释

4.1 static int tcp_write(struct sock *sk, unsigned char *from,

         int len, int nonblock, unsigned flags)

from待发送数据所在的用户缓冲区。

len待发送数据长度。

nonblock发送失败是否等待。

flags是否为OOB数据,OOB数据称为带外数据,需要立即发送给远端。

4.2 release_sock(sk);

              if (copied)

                     return(copied);

release_sock:将back_log队列中的数据尽可能的移动到receive_queue队列中

copied:已经发送的字节数

4.3  if (sk->keepopen)

       {

              send_sig(SIGPIPE, current, 0);

       }

     return(-EPIPE);

sk->keepopen:为1表示使用保活定时器

SIGPIPE:宏值为13,。

current:当前进程的数据结构。

0:。

send_sig:向进程发送信号。

EPIPE:宏值为32,在调用发送数据的函数是已经关闭了发送通道则返回次宏。

4.4 if (sk->state != TCP_ESTABLISHED &&

              sk->state != TCP_CLOSE_WAIT && sk->err == 0)

       {

              interruptible_sleep_on(sk->sleep);

              if (current->signal & ~current->blocked)

              {

                     sti();

                     if (copied)

                            return(copied);

                     return(-ERESTARTSYS);

              }

       }

sk->sleep:睡眠队列,类型为wait_queue结构

interruptible_sleep_on:此函数调用__sleep_on函数,使本进程进入TASK_INTERRUPTIBLE状态的睡眠等待,TASK_INTERRUPTIBLE状态的睡眠进程,只有中断操作将本进程状态设置为TASK_RUNNING方可被再次调度执行。

current->signal:信号,每个bit代表一种信号,信号值=位偏移值+1

current->blocked:进程信号屏蔽码。

current->signal &~current->blocked:有信号且不可屏蔽。

ERESTARTSYS:返回该错误表示用户程序应重新进行写操作。

4.5  if (!(flags & MSG_OOB))

       {

              copy = min(sk->mss - (skb->len - hdrlen), len);      

              memcpy_fromfs(skb->data + skb->len, from, copy);

              skb->len += copy;

              from += copy;

              copied += copy;

              len -= copy;

              sk->write_seq += copy;

       }

MSG_OOB:接收和发送的标志,宏值为1,此标志表示紧急数据

!(flags & MSG_OOB):此句表示如果不是紧急数据

sk->mss:最大报文长度,mss = mtu(最大传输单元)- ip– tcp

skb->len数据帧长度,ip + tcp + 负载数据。

copy数据帧长度,ip + tcp + 负载数据。

copy=min(sk->mss – (skb->len - hdrlen),len):此句表示如负载数据再增加len长度不会超过最大报文长度的限制则增加,否则只增加到最大报文长度的限制值

memcpy_fromfs复制用户缓冲区数据到内核缓冲区中。

skb->len += copy修改数据帧长度值。

from += copy修改待发送数据所在的用户缓冲区指针。

copied += copy修改已发送字节数变量。

len-=copy:修改待发送字节数变量

sk->write_seq+=copy:修改write_queue队列的序列号

4.6  if ((skb->len - hdrlen) >= sk->mss ||

              (flags & MSG_OOB) || !sk->packets_out)

              tcp_send_skb(sk, skb);

       else

              tcp_enqueue_partial(skb, sk);

              continue;

sk->packets_out已发送出去而尚未得到应答的数据包的个数。

(skb->len – hdrlen)>=sk->mss:达到了最大报文长度了就可以发送了,主要是为了减少小数据报的发送给网络造成压力,所以不是紧急数据的话尽量使数据包达到最大报文长度再发送

flags & MSG_OOB:如是紧急数据则立即发送

!sk->packets_out:如网络空闲则立即发送

tcp_send_skb参见《tcp.c文件的tcp_send_skb函数(17.doc》。

tcp_enqueue_partial参见《tcp.c文件的tcp_enqueue_partial函数(19.doc》。

4.7  copy = sk->window_seq - sk->write_seq;

       if (copy <= 0 || copy < (sk->max_window >> 1) || copy > sk->mss)

              copy = sk->mss;

       if (copy > len)

              copy = len;

copy = sk->window_seq – sk->write_seq当前窗口可容纳数据量。

sk->window_seqsent_seq值加上远端窗口的大小,本地将要发送的数据包的最后一个字节的序列号不可大于此值。

sk->write_seqwrite_queue队列的序列号

第一个if

第二个if

阅读(4261) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~