Golang TCP 服务器,如何向客户端写数据?

写了一个Golang TCP服务器,有两个不同的客户端链接这个服务器,这两个客户端之间需要互相发送/接收数据。

这里的处理逻辑非常的简单,先是服务器监听客户端请求。然后把第一个连接过来的客户端请求链接保存在一个变量中。
第二个客户端请求过来的时候,给服务器端发送过来一条消息,然后服务器把这条消息通过刚才保存的第一个链接发送给第一个客户端。

问题来了:
在write2Client(。。)函数中,我必须把第一个链接Close,第一个客户端才能够接收到转发过来的这条消息;如果不调用Close,则第一个无法接收到转发过来的数据。
这种处理显然是不正确的,没法发送第二条数据了。代码如下,请大家帮忙诊断一下。

func createTCPServer() {
    l, err := net.Listen("tcp", ":2000")
    if err != nil {
        log.Fatal(err)
    }

    var connFist net.Conn
    defer l.Close()

    for {
        // Wait for a connection.
        conn, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }

        // go func(c net.Conn) {
            if nil == connFist {
                connFist = conn
            } else {
                buf := make([]byte, 1024)
                uplen, err := conn.Read(buf)
        if err != nil {
            return
        }
                go write2Client(connFist, buf[:uplen])
                // connFist.Close()
                connFist = nil
                conn.Close()
            }
    }
}



func write2Client(co net.Conn, bb []byte) {
    // wlen, err := co.Write(bb)
    co.Write(bb)
    co.Close()
    co = nil
}

共 11 个回复


zeast

这样写客户端应该是可以收到消息的。可以贴出客户端代码看下。

# 0

qkevin123

我的客户端是Android,客户端收到消息的情况有两条,目前的代码客户端的确是可以收到消息的。
1,把connection close
2,在命令行界面按下Ctrl+C关闭服务器进程

问题是:把connection close了以后,后面的消息就没有办法继续发送了呀?所以这里不能关闭。
可是不关闭,客户端就收不到消息?

# 1

fsy412

一个客户端连接起一个goroutine处理

# 2

fhbzyc

瞎写

网上大把的例子 随便抄一个都能用

# 3

zeast

@qkevin123
你可以先简化下问题,用golang写一个简单的客户端看看是否可以收到消息。

# 4

qkevin123

@fsy412 一个连接一个goroutine也跑过,效果一样。

@zeast golang写的客户端可以收到,为什么?

# 5

zeast

@qkevin123
既然golang的客户端可以收到,那么服务器端没有问题的概率较大。可以检查下Android客户端网络数据接收实现。
如果检查之后感觉Android客户端也没有问题,那么可以用抓包工具看下网络包情况,应该可以断定是哪一边的问题,然后再分析。

# 6

qkevin123

@zeast, 谢谢,我在测试一下。

顺便问一个问题,这种tcp长连接,如果客户端断开了,服务器端怎么知道这种连接断开呢?Golang里面net.Conn里面没看到相同的通知方法?

# 7

testing

Read的时候会返回错误信息,依据这个就可以判断了

# 8

zeast

@qkevin123
诚如 @testing 所说,在读写一个断开的网络链接的时候,函数会返回错误。但是我认知中不是所有的客户端断开后,网络读写函数都会返回错误。
我遇到过当服务器向手机客户端发送消息,然后手机客户端在中途开启飞行模式的时候,写函数没有报错。还有什么突然掉电的情况。
我习惯在判断返回值基础上使用keepAlive, setDeadLine 等相关函数来确认链接情况。

# 9

qkevin123

以前做的项目中,Socket连接断开立马会收到通知。但Golang为什么要这样设计,有什么优点么?

# 10