完全なコードはhttps://groups.google.com/forum/#!topic/golang-nuts/e1Ir__Dq_gEからダウンロードできます。
誰かがこのサンプルコードをバグゼロに改善するのを手伝ってもらえますか?バグのないクライアント/サーバーコードを開発するのに役立つと思います。
私の開発手順:
- goroutineで複数の接続を処理できるサーバーを作成します。
- 単純なプロトコルで正常に動作するクライアントを構築します。
- クライアントを拡張して、複数のクライアントをシミュレートします(オプション-n = 1000クライアントをデフォルトとして使用)
- TODO:サーバーのロックを減らすようにしてください
- TODO:スループットを向上させるためにbufioを使用してみてください
このコードは非常に不安定で、次の3つの問題があります。
- 1000クライアントを起動します。そのうちの1つは、サーバーからの読み取り時に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
}
// ...
}