登录
首页 >  Golang >  Go问答

golang TCPConn.SetWriteDeadline doesn't seem to work as expected

来源:Golang技术栈

时间:2023-04-05 08:14:54 168浏览 收藏

从现在开始,我们要努力学习啦!今天我给大家带来《golang TCPConn.SetWriteDeadline doesn't seem to work as expected》,感兴趣的朋友请继续看下去吧!下文中的内容我们主要会涉及到golang等等知识点,如果在阅读本文过程中有遇到不清楚的地方,欢迎留言呀!我们一起讨论,一起学习!

问题内容

I'm trying to detect sending failures by inspecting the error returned by golang TCPConn.Write, but it's nil. I also tried using TCPConn.SetWriteDeadline without success.

That's how things happen:

  1. the server starts
  2. a client connects
  3. the server sends a message and the client receives it
  4. the client shuts down
  5. the server sends one more message: no error
  6. the server sends the third message: only now the error appears

Question : why only the second message to a non-existing client results in an error? How should the case be handled properly?

The code follows:

package main

import (
    "net"
    "os"
    "bufio"
    "fmt"
    "time"
)

func AcceptConnections(listener net.Listener, console 

The server console looks like this:

listening on 127.0.0.1:6666
client connected
hi there!
read from console: hi there!
msg sent: hi there!
this one should fail
read from console: this one should fail
msg sent: this one should fail
this one actually fails
read from console: this one actually fails
failed sending a message to network: write tcp 127.0.0.1:51194: broken pipe

The client looks like this:

package main

import (
    "net"
    "os"
    "io"
    //"bufio"
    //"fmt"
)

func cp(dst io.Writer, src io.Reader, errc chan

EDIT : Following JimB's suggestion I came up with a working example. Messages don't get lost any more and are re-sent in a new connection. I'm not quite sure though how safe is it to use a shared variable (connWrap.IsFaulted) between different go routines.

package main

import (
    "net"
    "os"
    "bufio"
    "fmt"
)

type Connection struct {
    IsFaulted bool
    Conn net.Conn
}

func StartWritingToNetwork(connWrap * Connection, errChannel chan 

正确答案

This isn't Go specific, and is a artifact of the underlying TCP socket showing through.

A decent diagram of the TCP termination steps is at the bottom of this page: http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm

The simple version is that when the client closes its socket, it sends a FIN, and receives an ACK from the server. It then waits for the server to do the same. Instead of sending a FIN though, you're sending more data, which is discarded, and the client socket now assumes that any more data coming from you is invalid, so the next time you send you get an RST, which is what bubbles up into the error you see.

Going back to your program, you need to handle this somehow. Generally you can think of whomever is in charge of initiating a send, is also in charge of initiating termination, hence your server should assume that it can continue to send until it closes the connection, or encounters an error. If you need to more reliably detect the client closing, you need to have some sort of client response in the protocol. That way recv can be called on the socket and return 0, which alerts you to the closed connection.

In go, this will return an EOF error from the connection's Read method (or from within the Copy in your case). SetWriteDeadline doesn't work because a small write will go though and get dropped silently, or the client will eventually respond with an RST, giving you an error.

以上就是《golang TCPConn.SetWriteDeadline doesn't seem to work as expected》的详细内容,更多关于golang的资料请关注golang学习网公众号!

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>