<p>I have 2 TCP servers, one is acting as a client to the other. Let's say A is client and B is server.</p>
<p>Every 30-60 seconds, A opens TCP connection, check the error, and close it immediately (basically a form of health check).</p>
<p>After many hours, there are a lot of CLOSE_WAIT TCP connections on server A.</p>
<p>What can I do on server B to acknowledge these CLOSE_WAIT connections and clean them up properly?</p>
<p><strong>EDIT</strong></p>
<p>The client code uses this library: <a href="https://github.com/tevino/tcp-shaker" rel="nofollow">https://github.com/tevino/tcp-shaker</a> because it skips the final ACK on Linux. I basically do the following:</p>
<pre><code>// Client Code
import "time"
import "github.com/tevino/tcp-shaker"
c := tcp.NewChecker(true)
c.InitChecker()
for {
err := c.CheckAddr("serverB:8080", 2 * time.Second)
if err != nil {
// do something with the error.
println(err.Error())
}
time.Sleep(30*time.Second)
}
</code></pre>
<p>The server-side code looks very much like this repo: <a href="https://github.com/firstrow/tcp_server" rel="nofollow">https://github.com/firstrow/tcp_server</a>.</p>
<pre><code>// Server Code
import "bufio"
import "net"
listener, err := net.Listen("tcp", "serverB:8080")
if err != nil {
println(err.Error())
return
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
if conn != nil {
conn.Close()
}
time.Sleep(time.Second)
continue
}
conn.SetWriteDeadline(time.Now().Add(5*time.Second))
defer conn.Close()
go func(conn net.Conn) {
reader := bufio.NewReader(conn)
for {
message, err := reader.ReadString('\n')
if err != nil {
conn.Close()
break
}
println(message) // Do something with the message.
}
}(conn)
}
</code></pre>
<p><strong>ONE SMALL NOTE</strong></p>
<p>The actual server is listening on TLS (and I have verified that it works), I just don't want to open TLS connection for simple health checking. </p>
<hr/>**评论:**<br/><br/>wheey: <pre><p>CLOSE_WAIT is due to the fact, as you mentioned, that client sent a FIN and system has initiated closing a connection. A is now waiting for B to close a connection and thus sends an ACK to the A which then closes a connection.</p>
<p>Problem here is either that B is not closing a connection or it does not listen for one.</p>
<p>If you could share a code A<->B maybe we can be more precise. </p></pre>pinpinbo: <pre><p>I have updated my post with a simplified code example. The error checking location is exactly where I put it on my actual code.</p></pre>i_regret_most_of_it: <pre><p>Hard to say without seeing the client code. Are you fully reading the response body? Are you sure you are always closing the connection? Are you re-using the http client?</p></pre>pinpinbo: <pre><p>Yes, the TCP library that I use always calls <code>Close()</code>. In this case I am not reusing the TCP connections.</p>
<p>I have updated my post with a simplified code example. The error checking location is exactly where I put it on my actual code.</p></pre>niosop: <pre><p>Try it without tcp-shaker? Might as well do a full TLS connection as well. One TLS setup/teardown every 30 seconds isn't going to hurt anything.</p></pre>wheey: <pre><p>There is probably some kind of lock when you are calling close. But, what I would suggest is putting goroutine in separate function and then on error rather call return then break;
PS. I had a problem before with SetWriteDeadline and sometimes it happened that it would never close connection.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传