• 端口复用setsockopt


    程序设计中的问题

      首先我们做一个测试,先启动server,然后启动client,用Ctrl+c终止server,在马上运行server,会导致出错,如下:(错误提示在代码中定义)

       这是由于,虽然server的应用程序终止了,但是TCP协议层的连接还未完全断开,因此不能马上监听同样的server端口,我们可以用netstat -apn|greap 6666查看一下端口号为6666的状态:

       server终止时,socket描述符会自动关闭并发FIN段给client,client收到FIN后处于CLOSE_WAIT状态,但是client并未终止,也没有关闭socket描述符,因此不会发FIN给server,因此server的TCP连接处于FIN_WAIT2状态。

      现在将client也使用Ctrl+c终止,在观察:

      client终止时自动关闭socket描述符,server的TCP连接收到client发的FIN段后处于TIME_WAIT状态。TCP协议规定,主动关闭连接的一方要处于TIME_WAIT状态,等待两个MSL的时间后才可以回到CLOSED状态,因为我们先终止了server,所以server是主动关闭连接的一方,在TIME_WAIT期间仍然不能再次监听同样的server端口。

      MSL在RFC1122中规定为两分钟,但是各操作系统的实现不同,在linux上一般是半分钟就可再次启动server了。

    端口复用

      在server的TCP连接没有完全断开之前不允许重新监听是不合理的,因为TCP连接没有完全断开是指connfd(127.0.0.0:6666)没有完全断开,而我们重新监听放入是listenfd(0.0.0.0:6666),虽然是占用同一个端口,但是IP地址不同,connfd对应的是与某个客户端通讯的一个具体的IP地址,而listenfd对应的是wildcard address,解决这个问题的方法是使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1,表示允许创建端口号相同但IP不同的多个socket描述符。使用方法如下:

      在server代码的socket()和bind()调用之间插入如下代码:

     有关setsockopt可以设置的其他选项在UNP第七章!

  • 相关阅读:
    Android:UI界面设计基础知识总结(一)
    Test:河北金力集团企业网集成
    Java中的异常处理try catch(第八周课堂示例总结)
    Java第七周课堂示例总结
    初入JavaWeb(半成品)
    Redis详解(4)--redis底层数据结构
    Go语言流程控制05--defer延时执行
    java==IO练习,文件切割合拼工具开发代码
    【洛谷 P3772】[CTSC2017]游戏(矩阵乘法+线段树)
    【LOJ #2865】「IOI2018」狼人(Kruscal重构树+扫描线)
  • 原文地址:https://www.cnblogs.com/LaiY9/p/14529116.html
Copyright © 2020-2023  润新知