2010-03-21 3 views
2

SocketAsyncEventArgs 개체에서 버퍼를 사용해야합니다. 기존의 소켓 방식으로SocketAsyncEventArgs 개체에서 버퍼를 사용하는 방법

우리는 다음과 같이 우리의 상태 개체를 캐스팅 것 :

clientState cs = (clientState)asyncResult.AsyncState; 

그러나, 3.5 프레임 워크는 다르다.

클라이언트에서 문자열이 청크로 도착했기 때문에 버퍼가 어떻게 작동하는지 확인할 수 없어서 char3을 발견 할 때 전체 문자열을 처리 할 수 ​​있습니다. 순간

코드 :

private void ProcessReceive(SocketAsyncEventArgs e) 
{ 
    string content = string.Empty; 

    // Check if the remote host closed the connection. 
    if (e.BytesTransferred > 0) 
    { 
     if (e.SocketError == SocketError.Success) 
     { 
      Socket s = e.UserToken as Socket; 
      //asyncResult.AsyncState; 

      Int32 bytesTransferred = e.BytesTransferred; 

      // Get the message received from the listener. 
      content += Encoding.ASCII.GetString(
       e.Buffer, e.Offset, bytesTransferred); 

      if (content.IndexOf(Convert.ToString((char)3)) > -1) 
      { 
       e.BufferList = null; 

       // Increment the count of the total bytes receive by the server 
       Interlocked.Add(ref this.totalBytesRead, bytesTransferred); 
      } 
      else 
      { 
       content += Encoding.ASCII.GetString(
        e.Buffer, e.Offset, bytesTransferred); 
       ProcessReceive(e); 
      } 
     } 
     else 
     { 
      this.CloseClientSocket(e); 
     } 
    } 
} 
+0

사용하여 코드를 수정 한'Buffer' 또는'BufferList', 그러나 결코 모두 같은 시간에. [To Wit] (https://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.bufferlist%28v=vs.90%29.aspx)'버퍼가 비 -null 값이며 BufferList 속성을 null이 아닌 값으로 설정하려고 시도하면 예외가 발생합니다.'BufferList가 null이 아니므로 'BufferList'를'null '로 설정하는 것은 의미가 없습니다. null인데,이 경우'BufferList'는 null이되거나'Buffer'는 null입니다.이 경우'GetString'은 이미'ArgumentNullException'을 던집니다. –

답변

5

내가 말함으로써 시작합니다 나는 .NET 3.5 소켓과 함께 일한 적이, 그래서이 답변이 추측의 비트입니다.

문제는 읽는 동안 일부 상태에 콘텐츠를 저장하지 않는다는 것입니다. 그래서 문제는 다음과 같습니다
첫째

  1. 당신은 전화 ProcessReceive : string content = string.Empty;

  2. 콘텐츠에 추가 : '내용 + = Encoding.ASCII.GetString (e.Buffer, e.Offset , ew.BytesTransferred)`

  3. 당신은 다시 ProcessReceive 전화 : string content = string.Empty;
  4. 을주기는 계속 콘텐츠는 항상로 설정됩니다 n 빈 문자열.

는 둘째
당신이 ProcessReceive을 요구하고 나머지 데이터를 수신하려면이 올바르지 않습니다. ReceiveAsync를 사용하여 기본 Socket에 다른 읽기를 수행해야합니다.

나는 당신이 중 하나를 사용 this blog post.

// You'll need some state object, if you don't already have one 
class AsyncServerState 
{ 
    public byte[] Buffer = new byte[8192]; // 8K buffer 
    public StringBuilder Content = new StringBuilder0; // Place to store the content as it's received 
    public SocketAsyncEventArgs ReadEventArgs = new SocketAsyncEventArgs(); 
    public Socket Client; 
} 

// You'll need to setup the state where ever you process your connect 
// something similar to this. 
void Accept_Completed(object sender, SocketAsyncEventArgs e) 
{ 
    if (e.SocketError == SocketError.Success) 
    { 
     Socket client = e.AcceptSocket; 
     AsyncServerState state = new AsyncServerState(); 
     state.ReadEventArgs.AcceptSocket = client; 
     state.ReadEventArgs.Completed += new EventHandler(            IO_Completed); 
     state.ReadEventArgs.UserToken = state; 
     state.Client = client; 
     state.ReadEventArgs.SetBuffer(state.Buffer, 0, state.Buffer.Length); 

     if (!client.ReceiveAsync(state.ReadEventArgs)) 
     { 
      // Call completed synchonously 
      ProcessReceive(state.ReadEventArgs); 
     } 
    } 
    ProcessAccept(e); 
} 

private void ProcessReceive(SocketAsyncEventArgs e) 
{   
    var state = e.UserToken as AsyncServerState; 

    // Check if the remote host closed the connection. 
    if (e.BytesTransferred > 0) 
    { 
     if (e.SocketError == SocketError.Success) 
     { 
      // Get the message received from the listener. 
      sting content = Encoding.ASCII.GetString(state.Buffer, 0, e.BytesTransferred); 

      // Append the received data to our state 
      state.Content.Append(content);       

      // Increment the count of the total bytes receive by the server 
      Interlocked.Add(ref this.totalBytesRead, bytesTransferred); 

      if (content.IndexOf(Convert.ToString((char)3)) > -1) 
      { 
       // Final Message stored in our state 
       string finalContent = state.Content.ToString(); 
       return;     
      } 
      else 
      { 
       // You need to issue another ReceiveAsync, you can't just call ProcessReceive again 
       if (!state.Client.ReceiveAsync(state.ReadEventArgs)) 
       { 
        // Call completed synchonously 
        ProcessReceive(state.ReadEventArgs); 
       }     
      } 
     } 
     else 
     { 
      this.CloseClientSocket(e); 
     } 
    } 
} 
관련 문제