⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 2_4网络代码阅读笔记(2) - china linux forum.htm

📁 包括较少的一些linux下的网络代码阅读笔记
💻 HTM
📖 第 1 页 / 共 2 页
字号:
            <BR>spin_lock(&amp;head-&gt;lock); <BR>for (tb = head-&gt;chain; tb; 
            tb = tb-&gt;next) <BR>if (tb-&gt;port == rover) <BR>goto next; 
            <BR>break; <BR>next: <BR>spin_unlock(&amp;head-&gt;lock); <BR>} 
            while (--remaining &gt; 0); <BR>&gt;&gt;&gt;&gt;下面几步判断究竟找到相应的端口没有. 
            <BR>tcp_port_rover = rover; 
            <BR>spin_unlock(&amp;tcp_portalloc_lock); <BR>/* Exhausted local 
            port range during search? */ <BR>ret = 1; 
            <BR>&gt;&gt;&gt;&gt;没有找到可用的端口 <BR>if (remaining &lt;= 0) <BR>goto 
            fail; <BR>/* OK, here is the one we will use. HEAD is <BR>* non-NULL 
            and we hold it's mutex. <BR>*/ <BR>&gt;&gt;&gt;&gt;终于找到了一个可用的. 
            <BR>snum = rover; 
            <BR>&gt;&gt;&gt;&gt;找到了合适的没有使用的端口,tc=NULL,下面就免去了对端口重用的检查了 <BR>tb = 
            NULL; <BR>} else { 
            <BR>&gt;&gt;&gt;&gt;用户给出了端口,这里判断是否在tcp_bhash中已经有同样的端口 
            <BR>&gt;&gt;&gt;&gt;如果有则tb指向包含这个端口的桶,没有则tb=NULL <BR>head = 
            &amp;tcp_bhash[tcp_bhashfn(snum)]; 
            <BR>spin_lock(&amp;head-&gt;lock); <BR>for (tb = head-&gt;chain; tb 
            != NULL; tb = tb-&gt;next) <BR>if (tb-&gt;port == snum) <BR>break; 
            <BR>} <BR>&gt;&gt;&gt;&gt;如果端口已经存在在tcp_bhash之中,则要对是否允许重用进行检查 <BR>if 
            (tb != NULL &amp;&amp; tb-&gt;owners != NULL) { 
            <BR>&gt;&gt;&gt;&gt;设置了fastreuse和reuse,且套接字状态不是倾听,则可以重用 <BR>if 
            (tb-&gt;fastreuse != 0 &amp;&amp; sk-&gt;reuse != 0 &amp;&amp; 
            sk-&gt;state != TCP_LISTEN) { <BR>goto success; <BR>} else { 
            <BR>&gt;&gt;&gt;&gt;对端口是否能够重用进行检查,代码放到下面分析 
            <BR>............................ <BR>} <BR>} <BR>ret = 1; 
            <BR>&gt;&gt;&gt;&gt;在没有任何端口重用的情况下.创建一个桶,并且连入到tcp_bhash的正确位置 <BR>if 
            (tb == NULL &amp;&amp; <BR>(tb = tcp_bucket_create(head, snum)) == 
            NULL) <BR>goto fail_unlock; <BR>&gt;&gt;&gt;&gt;如果这是第一个绑定这个端口的sock 
            <BR>if (tb-&gt;owners == NULL) { 
            <BR>&gt;&gt;&gt;&gt;如果这个端口设为reuse,而且不在倾听状态,则设置bind桶的fastreuse 
            <BR>&gt;&gt;&gt;&gt;这样后续的想绑定这个端口的sock将不用多作判断就可以直接重用了 <BR>if 
            (sk-&gt;reuse &amp;&amp; sk-&gt;state != TCP_LISTEN) 
            <BR>tb-&gt;fastreuse = 1; <BR>else <BR>tb-&gt;fastreuse = 0; <BR>} 
            else <BR>&gt;&gt;&gt;&gt;多个sock绑定这个端口 <BR>if (tb-&gt;fastreuse 
            &amp;&amp; 
            <BR>&gt;&gt;&gt;&gt;这个bind桶其它的sock都允许fastreust,如果这个sock不允许reuse 
            <BR>&gt;&gt;&gt;&gt;或者在倾听状态,则将fastreuse置为0, 
            <BR>&gt;&gt;&gt;&gt;则后面的想重用这个端口的就要进行上述的重重检查 <BR>((sk-&gt;reuse == 0) 
            || (sk-&gt;state == TCP_LISTEN))) <BR>tb-&gt;fastreuse = 0; 
            <BR>success: <BR>&gt;&gt;&gt;&gt;将端口号保存到sk-&gt;num中 <BR>sk-&gt;num = 
            snum; <BR>&gt;&gt;&gt;&gt;将重用同一个端口的sock用双向链表连接起来,我们这个sock放最前面. 
            <BR>if (sk-&gt;prev == NULL) { <BR>if ((sk-&gt;bind_next = 
            tb-&gt;owners) != NULL) <BR>tb-&gt;owners-&gt;bind_pprev = 
            &amp;sk-&gt;bind_next; <BR>tb-&gt;owners = sk; 
            <BR>&gt;&gt;&gt;&gt;前向指针指向bind桶的owners域 <BR>sk-&gt;bind_pprev = 
            &amp;tb-&gt;owners; 
            <BR>&gt;&gt;&gt;&gt;sock的prev指针指向了这个bind桶.当要这个sock要释放这个端口的时候 
            <BR>&gt;&gt;&gt;&gt;就可以直接根据这个指针找到相应的struct tcp_bind_bucket结构 
            <BR>sk-&gt;prev = (struct sock *) tb; <BR>} else { 
            <BR>BUG_TRAP(sk-&gt;prev == (struct sock *) tb); <BR>} <BR>ret = 0; 
            <BR>fail_unlock: <BR>spin_unlock(&amp;head-&gt;lock); <BR>fail: 
            <BR>local_bh_enable(); <BR>return ret; <BR>} 
            <BR><BR>下面是对本地端口重用的规则:(摘自tcp.h注释): 
            <BR>1:绑定到不同网络接口的套接字可以共享一个本地端口,如果不是这样,goto 2: 
            <BR>2:如果所有的套接字设置了reuse位,并且不处于TCP_LISTEN状态,则端口可以重用,如果 <BR>不是是这样,则goto 
            3: <BR>3:如果所有的套接字绑定到一个特定的本地地址,并且它们都不相同,则端口可以被重用 
            <BR><BR>对第二步,比较有意识,FTP服务器几乎天天在做这件事,为了对这种情况进行优化,特别在 
            <BR><BR>bind桶的定义(struct tcp_bind_bucket)中设置了一个标志位. <BR>当我们增加一个struct 
            sock到一个bind桶的链表中时,进行如下的检查 <BR>(newsk-&gt;reuse &amp;&amp; 
            (newsk-&gt;state != TCP_LISTEN)) <BR>只要所有的加入这个bind桶的struct 
            sock满足这个检查,这个标志将置位. 
            <BR>tcp_v[46]_verify_bind检查这个标志,如果设置了这个标志,并且struct sock的reuse标 
            <BR>志了设置了的话,就不 <BR>需要遍历这个bind桶上的struct sock链表,仅仅返回成功. 
            <BR>听起来好像作了很多工作,但必须这样作.在一些早期的实现中(例如FreeBSD),必须遍历 <BR>每个被FTP服务器打开的 
            <BR>数据端口链表.(这里几句翻不动了,自己看原文吧) <BR>* Needless to say, this does not 
            scale at all. With a couple <BR>* thousand FTP users logged onto 
            your box, isn't it nice to know that new <BR>* data ports are 
            created in O(1) time? I thought so. ;-) -DaveM 
            <BR>好了看完了注释,可以看看上面的代码了.让我们先看看它的定义bind桶的定义. <BR>struct 
            tcp_bind_bucket { <BR>unsigned short port; <BR>unsigned short 
            fastreuse; <BR>struct tcp_bind_bucket *next; <BR>struct sock 
            *owners; <BR>struct tcp_bind_bucket **pprev; <BR>}; 
            <BR>这里猜想上面说的标志为fastreuse,上面结构中owners怀疑就是复用到这个端口的所有 <BR>的struct 
            sock的链表. <BR>它们用struct sock结构的bind_next连接. 
            <BR><BR>&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;对端口重用进行检查的代码&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; 
            <BR><BR>&gt;&gt;&gt;&gt;得到链头 <BR>struct sock *sk2 = tb-&gt;owners; 
            <BR>int sk_reuse = sk-&gt;reuse; <BR>&gt;&gt;&gt;&gt;一次遍历一个struct 
            sock,这个sock绑定了这个端口 <BR>for( ; sk2 != NULL; sk2 = sk2-&gt;bind_next) 
            { <BR>&gt;&gt;&gt;&gt;如果满足了下面三个条件,端口重用就失败: 
            <BR>&gt;&gt;&gt;&gt;1.如果绑定的网络接口相同而且 
            <BR>&gt;&gt;&gt;&gt;2.这两个sock其中之一或者全部不允许重用(reuser=0),或者是已经绑定的sock正在 
            <BR>&gt;&gt;&gt;&gt; 倾听状态 <BR>&gt;&gt;&gt;&gt;3.这两个sock的接受地址均相同 
            <BR>&gt;&gt;&gt;&gt;其它情况就允许重用了.呵呵,看来重用不是太难 <BR>if (sk != sk2 
            &amp;&amp; <BR>sk-&gt;bound_dev_if == sk2-&gt;bound_dev_if) { <BR>if 
            (!sk_reuse || <BR>!sk2-&gt;reuse || <BR>sk2-&gt;state == TCP_LISTEN) 
            { <BR>if (!sk2-&gt;rcv_saddr || <BR>!sk-&gt;rcv_saddr || 
            <BR>(sk2-&gt;rcv_saddr == sk-&gt;rcv_saddr)) <BR>break; <BR>} <BR>} 
            <BR><BR>欢迎访问"Unix编程" <BR>telnet apue.dhs.org 2323 <BR>or 
            http://apue.dhs.org 
            <P class=small>文章选项: <A 
            href="http://www.linuxforum.net/forum/printthread.php?Cat=&amp;Board=linuxK&amp;main=147050&amp;type=post" 
            target=_blank><IMG align=absMiddle alt=打印 border=0 
            src="2_4网络代码阅读笔记(2) - China Linux Forum.files/print.gif"></A> 
        </P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE align=center border=0 cellPadding=4 cellSpacing=0 width="95%">
  <TBODY>
  <TR>
    <TD align=left class=small>&nbsp; </TD>
    <TD align=right class=small><A 
      href="http://www.linuxforum.net/forum/printthread.php?Cat=&amp;Board=linuxK&amp;main=147050&amp;type=thread" 
      target=_blank><IMG align=top border=0 
      src="2_4网络代码阅读笔记(2) - China Linux Forum.files/printthread.gif"> 打印</A> 
  </TD></TR></TBODY></TABLE><BR>
<TABLE align=center border=0 cellPadding=0 cellSpacing=0 width="95%">
  <TBODY>
  <TR>
    <TD class=tableborders>
      <TABLE border=0 cellPadding=3 cellSpacing=1 width="100%">
        <TBODY>
        <TR class=darktable>
          <TD align=right>
            <TABLE border=0>
              <TBODY>
              <TR>
                <TD class=navigation noWrap><IMG align=absMiddle alt=* 
                  src="2_4网络代码阅读笔记(2) - China Linux Forum.files/greyflat.gif">平坦模式&nbsp; 
                </TD>
                <TD class=navigation noWrap><A 
                  href="http://www.linuxforum.net/forum/showthreaded.php?Cat=&amp;Board=linuxK&amp;Number=147050&amp;page=120&amp;view=collapsed&amp;sb=5&amp;o=all&amp;vc=1"><IMG 
                  align=absMiddle alt=树状模式,一封一封读 border=0 
                  src="2_4网络代码阅读笔记(2) - China Linux Forum.files/threaded.gif">树状模式</A>&nbsp; 
                </TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE align=center border=0 cellPadding=0 cellSpacing=0 width="95%">
  <TBODY>
  <TR>
    <TD align=right>
      <FORM action=http://www.linuxforum.net/forum/jumper.php method=post><INPUT 
      name=Cat type=hidden> <SPAN class=onbody>前往讨论区 </SPAN><SELECT 
      class=formboxes name=board> <OPTION value=-CATJUMP-1>*Linux 社区和文化* 
        -----<OPTION value=new>&nbsp;&nbsp;&nbsp;社区公告栏<OPTION 
        value=uglyduck>&nbsp;&nbsp;&nbsp;社区服务台<OPTION 
        value=linuxnews>&nbsp;&nbsp;&nbsp;业界新闻与评论<OPTION 
        value=linuxtalk>&nbsp;&nbsp;&nbsp;自由软件杂谈<OPTION 
        value=software>&nbsp;&nbsp;&nbsp;Linux软件快递<OPTION 
        value=Tworkshop>&nbsp;&nbsp;&nbsp;中文MAN-PAGE计划(CMPP)<OPTION 
        value=tcl>&nbsp;&nbsp;&nbsp;Linux图书与评论<OPTION 
        value=job>&nbsp;&nbsp;&nbsp;招聘和求职<OPTION value=-CATJUMP-2>*Linux 
        桌面与办公自动化* -----<OPTION value=chinese>&nbsp;&nbsp;&nbsp;Linux 
        中文环境和中文化<OPTION value=office>&nbsp;&nbsp;&nbsp;Linux桌面与办公软件<OPTION 
        value=game>&nbsp;&nbsp;&nbsp;Linux 多媒体与娱乐版<OPTION 
        value=mozilla>&nbsp;&nbsp;&nbsp;自由之窗Mozilla<OPTION 
        value=laptop>&nbsp;&nbsp;&nbsp;笔记本电脑上的Linux<OPTION 
        value=-CATJUMP-3>*Linux 入门及网络应用* -----<OPTION 
        value=debian>&nbsp;&nbsp;&nbsp;Debian 一族<OPTION 
        value=nm>&nbsp;&nbsp;&nbsp;网络管理技术<OPTION 
        value=newbie>&nbsp;&nbsp;&nbsp;Linux 安装与入门<OPTION 
        value=web>&nbsp;&nbsp;&nbsp;WEB服务器和FTP服务器<OPTION 
        value=dns>&nbsp;&nbsp;&nbsp;域名服务器和邮件服务器<OPTION 
        value=proxy>&nbsp;&nbsp;&nbsp;Linux防火墙和代理服务器应用<OPTION 
        value=samba>&nbsp;&nbsp;&nbsp;文件及打印服务器<OPTION 
        value=training>&nbsp;&nbsp;&nbsp; 技术培训与认证<OPTION value=-CATJUMP-4>*Linux 
        高级应用* -----<OPTION selected 
        value=linuxK>&nbsp;&nbsp;&nbsp;Linux内核技术<OPTION 
        value=embedded>&nbsp;&nbsp;&nbsp;嵌入开发推进计划 (OpenARM)<OPTION 
        value=driver>&nbsp;&nbsp;&nbsp;Linux设备驱动程序<OPTION 
        value=cluster>&nbsp;&nbsp;&nbsp;Linux 集群技术<OPTION 
        value=db>&nbsp;&nbsp;&nbsp;LINUX平台数据库<OPTION 
        value=cpu>&nbsp;&nbsp;&nbsp;CPU 与 编译器<OPTION 
        value=security>&nbsp;&nbsp;&nbsp;系统和网络安全<OPTION value=-CATJUMP-5>*Linux 
        环境下的程序设计* -----<OPTION 
        value=kylix>&nbsp;&nbsp;&nbsp;LINUX下的快速开发工具(RAD)<OPTION 
        value=program>&nbsp;&nbsp;&nbsp;C/C++编程版<OPTION 
        value=php3>&nbsp;&nbsp;&nbsp;PHP 技 术<OPTION 
        value=java>&nbsp;&nbsp;&nbsp;Java&amp;jsp技术<OPTION 
        value=vrml>&nbsp;&nbsp;&nbsp;Shell编程技术<OPTION 
        value=perl>&nbsp;&nbsp;&nbsp;Perl 编 程<OPTION 
        value=python>&nbsp;&nbsp;&nbsp;Python 编 程<OPTION 
        value=xml>&nbsp;&nbsp;&nbsp;XML/Web Service 技术<OPTION 
        value=-CATJUMP-6>*永远的 UNIX* -----<OPTION 
        value=unix>&nbsp;&nbsp;&nbsp;永远的Unix<OPTION 
        value=bsd>&nbsp;&nbsp;&nbsp;FreeBSD世界<OPTION value=-CATJUMP-7>*IT 人生* 
        -----<OPTION value=life>&nbsp;&nbsp;&nbsp;IT 人生</OPTION></SELECT> <INPUT class=buttons name=Jump type=submit value=出发> 
</FORM></TD></TR></TBODY></TABLE>
<P>
<TABLE align=center border=0 cellPadding=0 cellSpacing=0 width="95%">
  <TBODY>
  <TR>
    <TD class=tableborders>
      <TABLE border=0 cellPadding=3 cellSpacing=1 width="100%">
        <TBODY>
        <TR class=darktable>
          <TD>
            <TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
              <TBODY>
              <TR>
                <TD align=left><A href="mailto:davidd@linuxforum.net">Contact 
                  Us</A> </TD>
                <TD align=right><A 
                  href="http://www.linuxforum.net/">LINUXFORUM.NET</A> 
              </TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></P></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -