2009-05-26 38 views
3

データグラムソケット(UDP)に基づいて反復サーバーを作成しようとしています。 これは、最初のrecvfrom()コールから取得した最初のクライアントへの接続を呼び出します(これは実際の接続ではありません)。 このクライアントにサービスを提供した後、私はUDPソケットを切断します(AF_UNSPECで接続を呼び出す) 次にrecvfrom()を呼び出して、次のクライアントから最初のパケットを取得します。接続されたデータグラムソケットを切断して再接続する

問題は、ループの2番目の反復でrecvfrom()の呼び出しが0になっていることです。クライアントは空のパケットを送信しないので、何が起きる可能性があります。

これはIAMのは、(擬似コード)を行うものです:

s = socket(PF_INET, SOCK_DGRAM, 0) 

bind(s) 

for(;;) 
{ 
    recvfrom(s, header, &client_address) // get first packet from client 
    connect(s,client_address) // connect to this client 
    serve_client(s); 
    connect(s, AF_UNSPEC); // disconnect, ready to serve next client 
} 

編集:私は誤って空のパケットを送信し、私のクライアントのバグを発見しました。 私の問題は、どこにもリクエストを送信する代わりにクライアントを待機させる方法です(サーバーは別のクライアントに接続されており、他のクライアントにはまだ対応していません)。

答えて

3

SOCK_DGRAMではconnect()は本当に不要です。

を呼び出すと、他のホストからのパケットの受信が停止されたり、送信が停止したりすることはありません。ちょっと気にしないでください。本当に役に立たないです。

修正:はい、明らかに、他のホストからのパケットの受信を停止します。しかし、サーバでこれを行うのはちょっとばかげている。なぜなら、他のクライアントはあなたが接続している間にロックアウトされるからだ。また、あなたはまだ浮かんでいる "チャフ"をキャッチする必要があります。おそらく、DGRAMソケットのconnect()に関連した競合状態があります。あなたがconnectを呼び出し、他のホストからのパケットがすでにバッファに入っているとどうなりますか?

また、0は空の(データなし)パケットが有効で、存在する可能性があるため(実際にはそれらを使用することが多い)、recvfrom()からの有効な戻り値です。だから、何かが成功したかどうかを確認することはできません。

おそらく、0バイトのパケットがすでにキューに入っていました。

誤ったデータグラムが誤って解釈される可能性を最小限に抑えるように、プロトコルを設計する必要があります。この理由から、空のデータグラムを使用せず、代わりにマジックナンバーを使用することをお勧めします。

UDPアプリケーションは、 "チャフ"パケットを認識して破棄することができなければなりません。遅かれ早かれ登場するだろう。

+0

Connectは、send()またはrecv()を使用しているときに、アドレスを受信し、送信する内部フィルタを設定します。 recv(): "SOCK_DGRAMソケットの場合、データは、接続呼び出しで指定された宛先アドレスの最初のキューに入れられたデータグラムから抽出されます"。 – codymanix

+0

あなたが正しいです、私のクライアントは(バグのために)空のパケットを送っていました。今私は別の問題があります。キュー内で待機する必要があるクライアントは、最初の要求パケット(サーバーから受信されない)を送信します。それから応答を受け取ろうとし、recvは-1を返します。クライアントを待たせるにはどうすればいいですか? – codymanix

+0

あなたはまだこの問題に直面していますか(あなたの投稿の編集部分)、またはconnectを削除して解決していますか? –

0

man connect

 
... 
If the initiating socket is not connection-mode, then connect() 
shall set the socket’s peer address, and no connection is made. 
For SOCK_DGRAM sockets, the peer address identifies where all 
datagrams are sent on subsequent send() functions, and limits 
the remote sender for subsequent recv() functions. If address 
is a null address for the protocol, the socket’s peer address 
shall be reset. 
... 
+1

だから何ですか?どのようにこれは私の質問に答えますか? – codymanix

+0

正確に何が問題だったのですか? –

+0

私が不明な場合は申し訳ありません。問題はrecvfrom()への2回目の呼び出しが0を返す理由です。私はこれが私のコードのバグであることを発見しました。 私の問題は今、クライアントがデータをどこにでも送るのではなく、クライアントを待機させる方法です。 – codymanix

-1

私が行ったように、誰もがこの全体にstumbples場合だけ修正。接続を切断するには、sockaddrのsa_familyメンバーをAF_UNSPECに設定して呼び出す必要があります。 AF_UNSPECに合格しただけではありません。

関連する問題