SO_REUSEADDR option makes socket server development options in SO_REUSEADDR people TIME_WAIT socket server development of upset upset TIME_WAIT

SO_REUSEADDR socket server development options and make people upset in the TIME_WAIT

Excerpt: https://www.cnblogs.com/qiaoconglovelife/p/5416715.html
 

This article updates, please move on my personal blog: https://blog.andyqiao.top/article/15/

1 found the problem  

  I'm developing a socket server program and over again, I found the people very upset a situation: each kill off the server process and restart when, bind error appears: error: 98, Address already in use. But then kill off the process, restart again when you bind a success . Really confusing. Do we always have to try twice before seem sincere? This unscientific!

  My first reaction is the time to kill the process, and did not fully relieved socket resources, down time caused by the second start, bind failure. So how successfully the third time of it?

  Find information: Some say TIME_WAIT mischief.

  Recall that under Linux TIME_WAIT about two minutes, so be reasonable. What resources are not freed it, is the port it? Wit I immediately decided to do experiments to find out. Start the server program, after establishing a connection with the client, kill off the server. Quickly enter the command in the terminal where: netstat -an | grep 9877. 9877 Here is what I intend to bind the server port. really:

  

  The results showed that 9877 port is in use, and the TCP TIME_WAIT state. In two minutes, I then execute the command netstat -an | grep 9877, world quiet, nothing.

  Finally he found the answer: it really is in the TIME_WAIT mischief.

2 to solve the problem

  I found the problem, but how to solve the problem yet. How can we end off the TIME_WAIT state? Otherwise, every time after commissioning, Baba should wait two minutes, then the next time debugging. This is stupid! Like a long time, but also thought out solutions. TCP TIME_WAIT that there is no option can close out of it? Open book! UNP Chapter 7 is talking about socket options. Really not found. However, I found SO_REUSEADDR options. About this option, the book says you can play the following four different functions:

  (1) SO_REUSEADDR allowed to start a listen server and bundled with its well-known ports, even before the establishment of the port as a port of their local connection still exists.

  (2) allows multiple instances of the same server to start on the same port, as long as each instance of a bundle of different local IP address.

  (3) SO_REUSEADDR allows a single process tied to the same port on multiple sockets, as long as each of the different binding specifies the local IP address.

  (4) SO_REUSEADDR bundle allows full repeat: when an IP address and port number to bind to a socket, if the transport protocol support the same IP address and port can also be tied to another socket . Generally this feature is only supported UDP socket.

  I encountered exactly in line with the case 1, and the book says: "All TCP socket server should specify this option to allow the server to be restarted in this case." So give it a try myself.

  

      The above two lines of code, to be set to allow this socket listenFd address reuse (on = 1, if on = 0 is not allowed to reuse). So that each bind time, if this port is in use, then, would bind to port "grab" over. I would not have the error. Perfect to solve the problem.

3 police may say

  Since TIME_WAIT so nasty, then what significance does it exist? After all, the server connection has been cut off in the country. I remember before when looking at UNP, the above mentioned seems to have continued open book:

  The book says, TIME_WAIT state exists for two reasons:

  (1) full-duplex reliably terminate the TCP connection;

  (2) allowing passage of the old section is repeated in the network.

  So, to explain, on a map:

  

  (1) ACK if the server sends last lost for some reason, then the client will resend FIN, such as the existence of TIME_WAIT, the server sends an ACK back to the client, if not TIME_WAIT, regardless of the customer has not received the ACK, the server has been switched off are connected, this time the client resends the FIN, the server will not send the ACK, but the RST, so that the given client. In other words, TIME_WAIT help to reliably achieve full-duplex TCP connection is terminated.

  When (2) If there are no TIME_WAIT, we can not yet reach the customer in the final ACK, on ​​the establishment of a new connection. So this time, if the customer receives this ACK, then, went wrong, must ensure that after the ACK completely dead, in order to establish a new connection. In other words, TIME_WAIT allow repetition of the old section disappeared in the network.

  Back to our question, because I was not properly disconnected after four ways to disconnect, and so there will be no last ACK problem. So, this is safe. However, the final version of the server, or do not set to port reusable. Remember.

  come on! Come on. study hard, improve every day.

  Also: UNP is a good book to take behold.

Excerpt: https://www.cnblogs.com/qiaoconglovelife/p/5416715.html
 

This article updates, please move on my personal blog: https://blog.andyqiao.top/article/15/

1 found the problem  

  I'm developing a socket server program and over again, I found the people very upset a situation: each kill off the server process and restart when, bind error appears: error: 98, Address already in use. But then kill off the process, restart again when you bind a success . Really confusing. Do we always have to try twice before seem sincere? This unscientific!

  我的第一反应是kill进程的时候,并没有完全释放掉socket资源,倒致第二次启动的时候,bind失败。那么第三次怎么又成功了呢?

  查资料:有人说是TIME_WAIT在捣鬼。

  回想一下,Linux下的TIME_WAIT大概是2分钟,这样也合情合理。那么没有释放掉的资源是什么呢,是端口吗?机智的我立刻决定做实验找出答案。启动服务器程序,在与客户建立连接之后,kill掉服务器。飞快地在terminal里输入命令:netstat -an|grep 9877。这里9877是我服务器打算绑定的端口。果然:

  

  结果显示9877端口正在被使用,并处于TCP中的TIME_WAIT状态。再过两分钟,我再执行命令netstat -an|grep 9877,世界清静了,什么都没有。

  终于找到了答案:果然是TIME_WAIT在捣鬼。

2 解决问题

  问题找到了,可是怎么解决问题呢。如何才能结束掉这个TIME_WAIT状态呢?否则每次调试之后,都要巴巴地等上两分钟,再进行下次调试。这太蠢了!想了好久,也没想出解决办法。那TCP中有没有能关闭掉TIME_WAIT的选项呢?翻书!UNP中第7章就是讲socket选项的。还真没有找到。但是,我找到了SO_REUSEADDR选项。关于此选项,书上说可以起到以下4个不同的功用:

  (1)SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知的端口,即使以前建立的将该端口用作他们的本地端口的连接仍存在。

  (2)允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。

  (3)SO_REUSEADDR 允许单个进程捆绑同一端口到多个套接字上,只要每次捆绑指定不同的本地IP地址即可。

  (4)SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口号已绑定到某个套接字上时,如果传输协议支持,同样的IP地址和端口还可以捆绑到另一个套接字上。一般来说本特性仅支持UDP套接字。

  我遇到的情况正好符合情况1,并且书上说了:“所有TCP服务器都应该指定本套接字选项,以允许服务器在这种情形下被重新启动。”那么试试看喽。

  

      上面两行代码,把此套接字listenFd设置为允许地址重用(on=1,如果on=0就是不允许重用了)。这样每次bind的时候,如果此端口正在使用的话,bind就会把端口“抢”过来。就不会报错了。完美解决问题。

3 察漏补缺

  既然TIME_WAIT这么讨厌,那它的存在有什么意义呢?毕竟服务器端已经中断掉连接了呀。记得之前在看UNP的时候,上面好像有提到过,继续翻书:

  书上说,TIME_WAIT状态有两个存在的理由:

  (1)可靠地实现TCP全双工连接的终止;

  (2)允许老的重复分节在网络中消逝。

  原来如此,解释一下,上个图:

  

  (1)如果服务器最后发送的ACK因为某种原因丢失了,那么客户一定会重新发送FIN,这样因为有TIME_WAIT的存在,服务器会重新发送ACK给客户,如果没有TIME_WAIT,那么无论客户有没有收到ACK,服务器都已经关掉连接了,此时客户重新发送FIN,服务器将不会发送ACK,而是RST,从而使客户端报错。也就是说,TIME_WAIT有助于可靠地实现TCP全双工连接的终止。

  (2)如果没有TIME_WAIT,我们可以在最后一个ACK还未到达客户的时候,就建立一个新的连接。那么此时,如果客户收到了这个ACK的话,就乱套了,必须保证这个ACK完全死掉之后,才能建立新的连接。也就是说,TIME_WAIT允许老的重复分节在网络中消逝。

  回到我们的问题,由于我并不是正常地经过四次断开的方式中断连接,所以并不会存在最后一个ACK的问题。所以,这样是安全的。不过,最终的服务器版本,还是不要设置为端口可复用的。切记。

  加油加油。好好学习,天天向上。

  另外:UNP是本好书,要好好看呀。

Guess you like

Origin www.cnblogs.com/LiuYanYGZ/p/11210970.html