I'm writing, running, debugging a TCP server on FreeBSD that my clients connect to. When the server crashes or comes down somewhat ungracefully, often I have issues where I can't bring the server back up because my bind() call fails. When this happens of course I can find the following in netstat -n:
Active Internet connections
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp4 0 0 192.168.2.xxx.12345 xx.yy.zz开发者_如何学JAVA.ww.54201 FIN_WAIT_2
This is pretty irritating as I sit here for a minute or 2 or 3 until it clears out. I have tried my best to avoid this:
if((socketId = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) ...
// Set socket to nonblocking. If this is < 0 there was a failure
if(fcntl(socketId, F_SETFL, O_NONBLOCK) < 0) ...
// Linger settings
struct linger so_linger;
so_linger.l_onoff = 1; // Turn linger option TRUE!
so_linger.l_linger = 0; // And inform to DO NOT LINGER
if(setsockopt(socketId, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)) < 0) ...
So, why am I getting the lingering behavior? This is on FreeBSD but I had the same issue on Linux before I ported my code here. I have tried to put in code so that when I "control-c" kill my server it should run a close on all these sockets and immediately exit. That did not seem to help
Try setting the socket option SO_REUSEADDR
.
SO_REUSEADDR indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses.
AIUI, the O/S won't usually allow you to bind
if there's a socket left hanging around on that port, and this call should tell the O/S to permit it.
You could also take a look at sysctls:
- net.inet.tcp.fast_finwait2_recycle
- net.inet.tcp.finwait2_timeout
setting recycle=1 and the timeout down to something sane (5k ms, your mileage may vary) helped quite a bit on one of my boxes..
HTH :)
-jamie
精彩评论