小妖女 发表于 2015-1-16 17:25:46

给大家带来分离Linux体系内核源码了解SYN_RECV

常用的linux命令,尤其是一些能帮你提高开发效率的命令,(eg:grep,awk,sed,split等);
在tcp_v4_do_rcv中,有上面一段代码,是关于TCP毗连创建时分的代码:
 
  if(sk->sk_state==TCP_LISTEN){
structsock*nsk=tcp_v4_hnd_req(sk,skb);
if(!nsk)
gotodiscard;
if(nsk!=sk){
if(tcp_child_process(sk,nsk,skb))
gotoreset;
return0;
}
}

  tcp_v4_hnd_req的前往值,分歧情形下分歧。
 
  NULL呈现毛病
 
  nsk==sk承受到SYN
 
  nsk!=sk承受到ACK
 
  承受到ACK包时,tcp_v4_hnd_req函数会新建一个sock布局,并设置其初始形态为SYN_RECV,并前往新建的sock布局。
 
  接着挪用tcp_child_process函数,改动新建的sock的形态为ESTABLISHED.
 
  (以下基于linux内核2.4.0)
 
  SYN_RECV形态,望文生义,是收到SYN包后应当置的形态。关于SYN_RECV形态,受某些教科书的误导,我之前一向了解为服务器收到SYN包后应当置此形态。也没细想究竟是置谁人socket的形态,比来在看三次握手协定在linux内核中的完成时,才细心思索这个成绩应当是置毗连套接字的形态而非监听套接字的形态。
 
  一般,SYN包只用于TCP三次握手协定中。罕见的tcp三次握手协定历程(固然另有同时毗连、
 
  半毗连等别的一些情形)以下:
 
  1、clientSYN包――>server
 
  2、client<――SYN包/ACK包server
 
  3、clientACK包――>server
 
  依据tcp形态图,对应下述4个形态的变更
 
  a、client发送终了,形态酿成SYN_SEND;
 
  b、server收到SYN报并发送ack确认包和SYN包,形态变成SYN_RECV
 
  c、client发送ack包终了,形态酿成ESTABLISHED
 
  d、server发送ack包终了,形态酿成ESTABLISHED
 
  在linux内核中,上述几个形态对应为TCP_SYN_SEND、TCP_SYN_RECV、TCP_ESTABLISHED.
 
  RFC793中关于SYN_RECV形态的形貌以下:
 
  SYN-RECEIVED-representswaitingforaconfirmingconnection
 
  requestacknowledgmentafterhavingbothreceivedandsenta
 
  connectionrequest.
 
  从下面能够看出,这个形态是在本端吸收到对端毗连哀求,并发送毗连对端哀求后,守候对端应对时所置的形态。以是,实质上毗连的历程是两边哀求应对的往返,应当称四次握手,只是罕见的使用以c/s形式为主,而linux、包含尽年夜部分操纵体系都把服务器真个应对和哀求封装在一个包内里。
 
  但在linux内核中,倒是在监听套接字收到了客户真个ACK包后,才创立毗连套接字并初始化为TCP_SYN_RECV形态,以下函数挪用干系:
 
  tcp_v4_rcv――>tcp_v4_do_rcv――>tcp_v4_hnd_req――>tcp_check_req――>
 
  tcp_v4_syn_recv_sock――>tcp_create_openreq_child……
 
  structsock*tcp_create_openreq_child(structsock*sk,structopen_request*req,structsk_buff*skb)
 
  {
 
  structsock*newsk=sk_alloc(PF_INET,GFP_ATOMIC,0);/*创立毗连sock布局*/
 
  if(newsk!=NULL){
 
  structtcp_opt*newtp;
 
  ……
 
  memcpy(newsk,sk,sizeof(*newsk));
 
  newsk->state=TCP_SYN_RECV;/*置初始形态为SYN_RECV*/
 
  //以下为一些初始化newsk布局的操纵
 
  ……
 
  }
 
  这里仿佛都一般了,但另有一点,服务器收到ACK包后,形态应当改成毗连形态,而此时毗连套接字的形态仍是TCP_SYN_RECV
 
  缘故原由在于如今对ack包还没处置完,^_^,以下:
 
  inttcp_v4_do_rcv(structsock*sk,structsk_buff*skb)
 
  {
 
  ……
 
  if(sk->state==TCP_LISTEN){//此处是监听套接字的形态
 
  structsock*nsk=tcp_v4_hnd_req(sk,skb);//取得了下面讲的毗连套接字
 
  if(!nsk)
 
  gotodiscard;
 
  if(nsk!=sk){//明显监听与毗连套接字不等
 
  if(tcp_child_process(sk,nsk,skb))//此处挪用tcp_rcv_state_process置套接字为毗连创建形态
 
  gotoreset;
 
  return0;
 
  }
 
  }
 
  ……
 
  }
 
  可见,在linux内核中,SYN_RECV形态的坚持工夫长短常长久的(也很难创立前提让此形态坚持),这也是我们实践使用中经由过程netstat基础看不到这个形态的缘故原由

</p>
在linux中学习命令的最好办法是学习Shell脚本编程,Shell脚本比起其他语言来学习简单,但是功能却十分强大.通过学习Shell编程,能让你掌握大量的linux命令。

飘灵儿 发表于 2015-1-18 17:58:57

对我们学习操作系统有很大的帮助,加深我们对OS的理解。?

变相怪杰 发表于 2015-1-27 08:10:37

选择交流平台,如QQ群,网站论坛等。

简单生活 发表于 2015-2-5 06:39:06

熟悉操作是日常学习Linux中的三大法宝。以下是作者学习Linux的一些个人经验,供参考:

admin 发表于 2015-2-11 08:01:39

Linux高手更具有鼓励新手的文化精神。如何在Linux社区获得帮助,需要说明的是你要有周全的思考,准备好你的问题,不要草率的发问。

深爱那片海 发表于 2015-3-2 01:10:13

Linux?最大的优点在于其作为服务器的强大功能,同时支持多种应用程序及开发工具,所以Linux操作系统有着广泛的应用空间。

灵魂腐蚀 发表于 2015-3-11 01:49:51

通过自学老师给的资料和向同学请教,掌握了一些基本的操作,比如挂载优盘,编译程序,在Linux环境下运行,转换目录等等。学了这些基础才能进行下面的模拟OS程序。?

第二个灵魂 发表于 2015-3-17 18:58:12

通过一条缓慢的调制解调器线路,它也能操纵几千公里以外的远程系统。

分手快乐 发表于 2015-3-24 21:07:20

就这样,我们一边上OS理论课,一边上这个实验,这样挺互补的,老师讲课,一步一步地布置任务
页: [1]
查看完整版本: 给大家带来分离Linux体系内核源码了解SYN_RECV