2016-07-28 40 views
0

Goのネットワーキング側に飛び込んでいます。私はTCP ClientとServer 。Golang TCPクライアントはサーバーからデータを受信せず、conn.Read()でハング/ブロックします

クライアントにサーバーに接続し、簡単なメッセージ(「こんにちは」)を正常に送信できるようになりました。しかし、私は、サーバーに応答を返すようにすることはできません(または、クライアントに応答を読み込ませる)ことはできません。

ここにコードがあります。私はそれがサーバーに問題はありません伝えることができるものから、

サーバー

Address := "localhost:9999" 
Addr, err := net.ResolveTCPAddr("tcp", Address) 
if err != nil { 
    log.Fatal(err) 
} 

listener, err := net.ListenTCP("tcp", Addr) 
if err != nil { 
    log.Fatal(err) 
} 
defer listener.Close() 

//server loop 
for { 
    conn, err := listener.Accept() 
    if err != nil { 
     continue 
    } 

    go handle(conn) 
} 

func handle(c net.Conn) { 

    totalBytes, message := connRead(c) 
    fmt.Println(c.RemoteAddr()) 

    fmt.Println(string(message[:totalBytes])) 

    c.Write([]byte("Hi")) 
    fmt.Println("Replied") 
    c.Close() 
} 

func connRead(c net.Conn) (int, []byte) { 
    buffer := make([]byte, 4096) 
    totalBytes := 0 

    for { 
     n, err := c.Read(buffer) 
     totalBytes += n 
     if err != nil { 
      if err != io.EOF { 
       log.Printf("Read error: %s", err) 
      } 
      break 
     } 

    } 
    return totalBytes, buffer 
} 

クライアント

tcpAddr, err := net.ResolveTCPAddr("tcp", "localhost:9999") 
    if err != nil { 
     log.Fatal(err) 
    } 
    conn, err := net.DialTCP("tcp", nil, tcpAddr) 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer conn.Close() 

    _, err = conn.Write([]byte("Hello")) 
    if err != nil { 
     log.Fatal(err) 
    } 

    tBytes, resp := connRead(conn) 
    fmt.Println(tBytes) 
    fmt.Println(string(resp[:tBytes])) 

func connRead(c net.Conn) (int, []byte) { 
    buffer := make([]byte, 4096) 
    totalBytes := 0 

    for { 
     fmt.Println("Stuck?") 
     n, err := c.Read(buffer) 
     fmt.Println("Stuck.") 
     totalBytes += n 
     fmt.Println(totalBytes) 
     if err != nil { 
      if err != io.EOF { 
       log.Printf("Read error: %s", err) 
      } 
      break 
     } 

    } 
    return totalBytes, buffer 
} 

。クライアントを実行すると、すべてがfmt.Println("Stuck?")の直後に停止します。これはどういうわけか、n, err := c.Read(buffer)のステートメントで台無しになっていることを信じています。クライアントがCtrl-Cを押しても、サーバはmesseageの長さ(5)とメッセージ( "Hello")を出力しません。私がクライアントの読み書きをコメントアウトすると、物事はスムーズに実行されます。

私は回答のためにグーグルを試みましたが、何も出てこなかった。

私は間違っていますか?クライアントでconn.Read()を間違って使用していますか?

EDIT:

私は実際のLinuxへのアクセス権を持っているので、ここSIGQUITは適切な機能のためのダンプです。

サーバー

http://pastebin.com/itevngCq

クライアント

http://pastebin.com/XLiKqkvs

+1

から、それらの多くのバイトを読み取るためにバイト数を読みますクライアントとサーバーのブロックがEOFに接続されているように見えます。実行中のアプリケーションにSIQUITを送信して、ブロックされた場所を確認します。 –

+0

私はSIGQUITをサポートしていないWin 7を利用しています。 – JimDoe

+0

両方のプログラムは読み取り時にブロックされます。ピアの片方または両方は、他のピアのブロックを解除するために、接続の[書き込み側を閉じる](https://godoc.org/net#TCPConn.CloseWrite)すべきです。あるいは、メッセージのフレーミングを追加して、完全なメッセージを読んだ後に読み上げを停止することもできます。 –

答えて

1
for { 
    n, err := c.Read(buffer) 
    totalBytes += n 
    if err != nil { 
     if err != io.EOF { 
      log.Printf("Read error: %s", err) 
     } 
     break 
    } 

} 

あなたが接続から読んでいるので、EOFエラーが

01を発生するまでそれはありますあなたが実際に接続が閉じられますCtrl + Cクライアント側を押すことで、接続

を閉じるまで

conn.Write([]byte("Hello")) 

上記の文はまったくEOFに到達しないので、EOFは、サーバー側で発生し、それは理由がありますあなたがこの作品を作りたい場合は、なぜそれがループのためのサーバ側を終了し、これらの

127.0.0.1:**** 
Hello 
Replied 

を印刷しているあなたは、EOF

までの接続を読んではならない他の多くのalternatがあります。このためには

  1. デリミタを選択し、デリミタが発生するまでサーバで読み取り、それ以降に応答します。このlink
  2. を確認し、実際のメッセージを送信する前に、クライアント側から読み取るバイト数を送信し、まずサーバ側から読み込まれた後、迅速に接続
+0

ありがとうございます。私は代替番号1を使うことにしました。 しかし、今度は、サーバーからの応答を受け取った後、同じクライアントから別のメッセージを送信しようとすると、サーバーは2番目のメッセージを受け取っていないように見えます。 – JimDoe

+0

@ジムドーあなたが書いたものを共有することができますので、私はあなたを助けることができます – Raghu

+0

もちろん! クライアント: http://pastebin.com/k3B0zuVr サーバー: http://pastebin.com/9AXXjVwx 2番目のメッセージを送信します。しかし、私はサーバーから0バイト戻ってきます。 – JimDoe

関連する問題