1

C# ソケット (非同期モード) を使用しており、メッセージを正しく解析するには、ストリームから正確なバイト数を読み取る必要があります。私たちのシステムのメッセージは非常に長いので、socket.EndRead 操作は、socket.BeginRead で要求されたよりも少ないバイト数を返すようです。正確なバイト数が読み取られた場合にのみ、C# ソケット マーク操作が完了する可能性はありますか??? NetworkStream を使用していますか???\

IAsyncRes ar = socket.BeginRead(1Mb byte message)
ar.Handle.Wait() // --> will signal ONLY when 1Mb us read !!!!
socket.EndRead() 

更新:

私はC#イテレータでそれを解決しました。(irator ループを実行し、MoveNext の実行を担当するスレッドはここには示されていません)

protected IEnumerator<IAsyncResult> EnumReceiveExact(byte[] array)
        {


            int offset = 0;

            while (offset < array.Length)
            {
                SocketError err = SocketError.Success;
                IAsyncResult ar = _socket.BeginReceive(array, offset, array.Length - offset, SocketFlags.None, out err, null, null);
                Console.WriteLine("{0}:err:{1}", this, err);
                if (err != SocketError.Success)
                {
                    _socket.Close();
                    throw new Exception("Error " + err);
                }

                yield return ar;
                while (!ar.IsCompleted)
                {
                    yield return ar;
                }

                offset += _socket.EndReceive(ar, out err);
                if (err != SocketError.Success)
                {
                    _socket.Close();
                    throw new Exception("Error " + err);
                }

            }

        }
4

1 に答える 1

0

列挙子を使用して適切に呼び出します。ただし、実行中のスレッドをブロックするため、外部コードがasyncresultsでWaitOneを呼び出すだけではないことを願っています。

このスタイルの非同期コーディングが気に入った場合は、NuGetのWintellect AsyncEnumeratorを確認してください。イテレーターも使用され、コードのリソース効率が非常に高くなり、キャンセルと例外を処理する方法が簡単になり、APM終了メソッドがすべて呼び出されるようになります。

私は以前、正確な読み取りの問題に次のように対処しました。

1)ソケットで送信されるデータに長さプレフィックスを追加します
。2)次のメソッドを使用してソケットで機能するヘルパークラスを定義します。

public IAsyncResult BeginRead(AsyncCallback callback)
// Calculate whether to read length header or remaining payload bytes
// Issue socket recieve and return its IAsyncResult

public MemoryStream EndRead(IAsyncResult result)
// Process socket read, if payload read completely return as a memorystream
// If length header has been recieved make sure buffer is big enough
// If 0 bytes recieved, throw SocketException(10057) as conn is closed

public IAsyncResult BeginSend(AsyncCallback callback, MemoryStream data)
// Issue sends for the length header or payload (data.GetBuffer()) on the first call

public Boolean EndSend(IAsyncResult result)
// Process bytes sent, return true if payload sent completely.
// If 0 bytes sent, throw SocketException(10057)

したがって、ループで呼び出す必要がありますが、通常の非同期操作のように見えます。たとえば、非同期チェックと例外処理なしで非同期操作を介して呼び出されます。

do
{
    socketHelper.BeginSend(ae.End(1, ar => socketHelper.EndSend(ar)), sendData);
    yield return 1;
    doneSend = socketHelper.EndSend(ae.DequeueAsyncResult());
} 
while (!doneSend);
于 2012-05-31T10:07:51.360 に答える