2011-01-31 2 views
3

TCPプロトコルの.NETソケットを使用するシングルスレッドサーバーがあり、Socket.Pool(),Socket.Select(),Socket.Receive()です。送信するにはMono/LinuxでSocket.SendAsyncが順序通りに送信されていません

、私が使用:

public void SendPacket(int clientid, byte[] packet) 
{ 
    clients[clientid].socket.Send(packet); 
} 

しかし、一つのクライアント(全体のメインスレッドを停止)に大量のデータを送信するとき、それは非常に遅かったので、私はこれでそれを置き換える:

public void SendPacket(int clientid, byte[] packet) 
{ 
    using (SocketAsyncEventArgs e = new SocketAsyncEventArgs()) 
    { 
     e.SetBuffer(packet, 0, packet.Length); 
     clients[clientid].socket.SendAsync(e); 
    } 
} 

.NETでWindows上で正常に動作します(完璧かどうかわかりません)が、LinuxではMonoでパケットが破棄されるか並べ替えられます(わかりません)。 Socket.Send()を使って遅いバージョンに戻すことは、Linux上で動作します。 Source for whole server

Linuxで動作するnon-blocking SendPacket()関数の記述方法は?

答えて

0

私はasyncメソッドを悪用しないと言っています。あなたはこれが絶対に秩序を維持しなければならないという証拠はどこにもないでしょう。それはスレッドに配布されるscheulerを待ち行列に入れ、実装の詳細まで自分で開くドキュメントごとにoderが保持されていないことを無視することによって、

最高の可能性があるに:

  • ソケットあたりのキューを持っています。
  • このキューにdastaを書き込み、ワーカースレッドが存在しない場合は、スレッドを処理する作業項目(ThreadPool)を開始します。

このようにして、順序を維持する個別の別個のキューがあります。 1つのスレッドのみが1つのキュー/ソケットを処理します。

+0

キューは不要です。これは、SendAsyncが内部的に行うためです。 – Marlon

+0

ああ、いいえ。 SendAsyncはマルチプルスレッドにmulötipel呼び出しを行います。これは、OPが経験したように間違っているかもしれません。 QuarantessはありませんSendAsyncへの4回の呼び出しは正しい順序で処理されます。 – TomTom

1

私は、あなたのusingステートメントとあなたのSendAsyncコールと関係があると思います。おそらくeは範囲外になり、廃棄中であり、SendAsyncはまだバッファを処理しています。しかし、これは例外をスローする可能性があります。私は本当に推測しています。 usingステートメントを削除して、何が起こるかを確認してください。

+0

OutOfMemoryExceptionが存在しないため、 'using'が追加されました。 – exe

+0

BeginSendを使ってみましたか? – Marlon

+0

OK、 'Socket.BeginSend'が動作しているようです。 – exe

0

私は同じ問題を抱えています。 LinuxとWindowsはSendAsyncと同じように反応しません。時にはLinuxがデータを切り捨てることもありますが、回避策があります。まず、キューを使用する必要があります。 SendAsyncを使うたびに、コールバックをチェックする必要があります。 e.Offset + e.BytesTransferred < e.Buffer.Lengthの場合は、e.SetBuffer(e.Offset + e.BytesTransferred、e.Buffer.Length - e.BytesTransferred -e.Offset)だけで済みます。再度SendAsyncを呼び出します。

私はなぜmono-linuxがすべてのデータを送信する前に完了していると信じていないのか分かりませんが、確信しています。

関連する問題