全部博文(41)
分类: LINUX
2009-08-25 15:24:03
tcp.c文件的tcp_select函数
978计划工作组
/*
* Wait for a TCP event.
*
* Note that we don't need to set "sk->inuse", as the upper select layers
* take care of normal races (between the test and the event) and we don't
* go look at any of the socket buffers directly.
*/
static int tcp_select(struct sock *sk, int sel_type, select_table *wait)
{
if (sk->state == TCP_LISTEN)
return tcp_listen_select(sk, sel_type, wait);
switch(sel_type) {
case SEL_IN:
if (sk->err)
return 1;
if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
break;
if (sk->shutdown & RCV_SHUTDOWN)
return 1;
if (sk->acked_seq == sk->copied_seq)
break;
if (sk->urg_seq != sk->copied_seq ||
sk->acked_seq != sk->copied_seq+1 ||
sk->urginline || !sk->urg_data)
return 1;
break;
case SEL_OUT:
if (sk->err)
return 1;
if (sk->shutdown & SEND_SHUTDOWN)
return 0;
if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
break;
/*
* This is now right thanks to a small fix
* by Matt Dillon.
*/
if (sk->prot->wspace(sk) < sk->mtu+128+sk->prot->max_header)
break;
return 1;
case SEL_EX:
if (sk->urg_data)
return 1;
break;
}
select_wait(sk->sleep, wait);
return 0;
}
用于处理各种探测类型,具体包括:SEL_IN、SEL_OUT和SEL_EX。
SEL_IN:宏值为1,探测是否有数据可读取。
sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV:连接建立期间,需返回0。
RCV_SHUTDOWN:宏值为1,接收通道被关闭后所处的状态,即远端发送了FIN数据包,此时tcp_select函数应返回1。
sk->acked_seq==sk->copied_seq:相等表无数据可读取,所以返回0。
sk->acked_seq:表示本地希望接收到的下一个数据序列号。
sk->copied_seq:本地已被读取的最后一个数据的序列号加1。
sk->urg_seq:紧急数据序列号。
sk->urginline:此标志位表示怎样对待紧急数据,如果该标志位被设置为1,则将紧急数据处理为普通数据。即在读取时,不再进行区别对待。
sk->urg_data:为1表接收到了紧急数据。
sk->urg_seq != sk->copied_seq:
sk->acked_seq != sk->copied_seq+1:
SEL_OUT:宏值为2,表示探测对应套接字发送缓冲区的空闲空间大小是否满足发送需求。
SEND_SHUTDOWN:宏值为2,发送通道关闭,即本地主动发送FIN 数据包。
sk->prot->wspace(sk):返回发送缓冲区当前空闲空间大小。
sk->mtu:表示最大传输单元,是本地网络加于本地的数据包大小限制。
sk->prot->max_header:最大链路层首部长度,tcp协议的max_header初始值是128。
SEL_EX:宏值为4,此处表示是否接收到了紧急数据。