完整代码可以在https://groups.google.com/forum/#!topic/golang-nuts/e1Ir__Dq_gE下载
任何人都可以帮助我将此示例代码改进为零错误吗?我认为这将帮助我们开发一个没有错误的客户端/服务器代码。
我的开发步骤:
- 创建一个可以通过 goroutine 处理多个连接的服务器。
- 构建一个可以使用简单协议正常工作的客户端。
- 扩展客户端以模拟多个客户端(默认使用选项 -n=1000 个客户端)
- TODO:尽量减少服务器的锁
- TODO:尝试使用 bufio 来提高吞吐量
我发现这段代码非常不稳定,包含三个问题:
- 启动 1000 个客户端,其中一个在从服务器读取时发生 EOF。
- 启动 1050 个客户端,很快打开的文件太多(没有打开任何客户端)。
启动 1020 个客户端,出现带有长跟踪堆栈的运行时错误。
Start pollServer: pipe: too many open files panic: runtime error: invalid memory address or nil pointer dereference [signal 0xb code=0x1 addr=0x28 pc=0x4650d0]
在这里,我粘贴了我更简化的代码。
const ClientCount = 1000
func main() {
srvAddr := "127.0.0.1:10000"
var wg sync.WaitGroup
wg.Add(ClientCount)
for i := 0; i < ClientCount; i++ {
go func(i int) {
client(i, srvAddr)
wg.Done()
}(i)
}
wg.Wait()
}
func client(i int, srvAddr string) {
conn, e := net.Dial("tcp", srvAddr)
if e != nil {
log.Fatalln("Err:Dial():", e)
}
defer conn.Close()
conn.SetTimeout(proto.LINK_TIMEOUT_NS)
defer func() {
conn.Close()
}()
l1 := proto.L1{uint32(i), uint16(rand.Uint32() % 10000)}
log.Println(conn.LocalAddr(), "WL1", l1)
e = binary.Write(conn, binary.BigEndian, &l1)
if e == os.EOF {
return
}
if e != nil {
return
}
// ...
}