2012-03-13 11 views
9

私はGoでエレベーター用のサーバーを作っていますが、TCP接続でゴルーチンとして "ハンドラー"という関数を実行しています。 接続から読み取る必要があり、一定の時間内に信号が検出されない場合はエラーを返すようにします。どのようにしてnet.Readをゴランの入力待ちにすることができますか?

限り、私はそれがうまく動作しているようだ接続上のものを送信するクライアントを持っていますが、できるだけ早くクライアントが停止するようnet.Read機能を送信することは、エラーEOFを返し、全く遅延なしでループを開始するよう
func handler(conn net.Conn){ 
    conn.SetReadTimeout(5e9) 
    for{ 
     data := make([]byte, 512) 
     _,err := conn.Read(data) 
    } 
} 

これは、読み取りが正常に動作するはずですが、何かを読み取るたびに接続を閉じて開いていなくても、別の方法で問題を処理することを提案できますか?

+2

conn.SetReadTimeout(5E9 )あなたが望むものではありません。 SetReadTimeoutは、継続時間ではなく絶対時間を求めます。 "time.Seconds * 10"と指定してみると、コンパイラは不平を言うでしょう。上記のことは、1970年1月1日以降に接続がタイムアウトになることを望んでいることです。したがって、まったく待ちません。代わりに、conn.SetReadTimeout(time.Now()。Add(time.Seconds * 10))の効果を10秒間のタイムアウトにする必要があります。 – Crunge

答えて

19

私は思ったとおりに読み込みが行われています。あなたがnetを望むように聞こえる。Goのチャンネルのように動作する。これは、外出先では非常に簡単ですだけで実行しているゴルーチンでnet.Readをラップし、ゴルーチンが本当に安いですチャンネルからの読み込みを選択使用し、そのチャネルに

例です:

ch := make(chan []byte) 
eCh := make(chan error) 

// Start a goroutine to read from our net connection 
go func(ch chan []byte, eCh chan error) { 
    for { 
    // try to read the data 
    data := make([]byte, 512) 
    _,err := conn.Read(data) 
    if err != nil { 
     // send an error if it's encountered 
     eCh<- err 
     return 
    } 
    // send data if we read some. 
    ch<- data 
    } 
}(ch, eCh) 

ticker := time.Tick(time.Second) 
// continuously read from the connection 
for { 
    select { 
    // This case means we recieved data on the connection 
    case data := <-ch: 
     // Do something with the data 
    // This case means we got an error and the goroutine has finished 
    case err := <-eCh: 
     // handle our error then exit for loop 
     break; 
    // This will timeout on the read. 
    case <-ticker: 
     // do nothing? this is just so we can time out if we need to. 
     // you probably don't even need to have this here unless you want 
     // do something specifically on the timeout. 
    } 
} 
+2

この方法で、['time.Tick'](https://golang.org/pkg/time/#Tick)の使用を明示的に警告しています。 –

+0

@DaveC:シングルチッカーを使用するようにコードを更新しました。 – nfirvine

+0

また、1秒よりはるかに小さい値がより適切であると言えます。 – nfirvine

0

net.ConnがGCの観点から到達不能オブジェクトになるため、ガベージコレクタ(GC)が接続の一端を閉じる可能性があります。これを防ぐには:クライアントが送信を停止した後、クライアント接続がコードでアクセス可能な変数に格納されていることを確認します。

もう1つのオプションは、プログラムのどこかで接続の一方の端を認識しないで閉じることです。

+0

私はあなたが間違っていると思って落ちましたが、あなたが正しいかもしれないと思います。それで、私はATMを落とさないようにしていません。 – nfirvine

関連する問題