2010-03-18 3 views
1

stream.DataAvailable을 사용하여 처리가 끝났는지를 판단하려고하지만 때로는 값이 거짓이지만 가끔씩 다시 진실한 경우가 있습니다. 이.net TcpClient를 사용하여 NetWorkStream이 끝나는 시점을 판단하려면 어떻게해야합니까?

int connectCounter = 0; 

while (connectCounter < 1200) 
{ 
    if (stream.DataAvailable) 
    { 
     while (stream.DataAvailable) 
     { 
      byte[] buffer = new byte[bufferSize]; 
      int flag = stream.Read(buffer, 0, buffer.Length); 
      string strReadXML_t = System.Text.Encoding.Default.GetString(buffer); 
      strReadXML = strReadXML + strReadXML_t.Replace("\0", string.Empty);  
     } 

     if (strReadXML.Substring(strReadXML.Length - 1, 1).Equals(">")) 
     { 
      break; 
     } 
    } 
    Thread.Sleep(100); 
    connectCounter++; 
} 

처럼 '>'카운터를 설정하고 기호로 끝을 판단하는 것은 그것을 다루는 좋은 methord가? 감사합니다!

답변

0

시도 asynchronous reading.
콜백이 호출되면 기존 데이터 버퍼를 읽고 BeginRead을 다시 호출 할 수 있습니다. 따라서 더 많은 데이터가 수신되면 콜백이 다시 호출됩니다. 같은

뭔가 :

void DataReceived(IAsyncResult result) ///I am not sure about the parameters. 
{ 
    ///read data from buffer 
    networkstream.BeginRead(
       buffer, 0, buffer.Length, 
       new AsyncCallback(DataReceived), 
       null); 
} 

나는이 꽤 괜찮은 방법이라고 생각합니다.

1

몇 가지 옵션이 있습니다. 동기, 읽기 차단 또는 비동기 IO 패턴을 사용할 수 있습니다.

단순히 stream.Read()를 호출하면 데이터가 사용 가능할 때까지 호출이 차단되고 TCP 시간 초과까지 영원히 대기합니다. 네가 그걸하고 싶지 않은 것 같아. 데이터를 완전히 읽으려면 최대 120 초 (1200ms * 100)를 기다려야합니다. 이 같은

뭔가 :

private class AsyncState 
{ 
    public NetworkStream ns; 
    public ManualResetEvent e; 
    public byte[] b; 
    public String strReadXML; 
} 

public void Run() 
{ 
    TcpClient client ;//= ... 
    NetworkStream networkStream = client.GetStream(); 
    byte[] buffer = new byte[1024]; 

    var completedEvent = new ManualResetEvent(false); 

    networkStream.BeginRead(buffer, 0, buffer.Length, 
          AsyncRead, 
          new AsyncState 
          { 
           b = buffer, 
           ns = networkStream, 
           e = completedEvent, 
           strReadXML = "" 
          }); 

    // do other stuff here. ... 

    // finally, wait 120s for the reading to complete 
    bool success = completedEvent.WaitOne(1200*100, false); 
    if (!success) 
    { 
     client.Close(); 
    } 
} 


private void AsyncRead(IAsyncResult ar) 
{ 
    AsyncState state = ar as AsyncState; 
    int n = state.ns.EndRead(ar); 
    if (n == 0) 
    { 
     // no more bytes to read 
     // signal completion 
     state.e.Set(); 
     return; 
    } 

    // state.buffer now contains the bytes read 

    string s = System.Text.Encoding.Default.GetString(state.b); 
    state.strReadXML = state.strReadXML + s.Replace("\0", string.Empty); 

    if (state.strReadXML.EndsWith(">")) 
    { 
     // got the "end". signal completion 
     state.e.Set(); 
     return; 
    } 

    // read again 
    state.ns.BeginRead(state.b, 0, state.b.Length, AsyncRead, state); 
} 
+0

감사합니다. 저에게 많은 도움이됩니다! :) –

+0

이 코드에는 여전히 한 가지 문제가 있습니다. int n = state.ns.EndRead (ar); if (n == 0) { // 읽을 바이트가 더 이상 없음 // 신호 완료 state.e.Set(); 반환; } n == 0 인 경우 methord가 반환되지만 단순히 스트림에 약간의 인터럽트가있는 경우 n == 0으로 읽을 바이트가 더 이상 없다고 판단 할 수 없습니다. 정확한 이유는 모르겠다. 아마도 밴드가 이유일지도 몰라. –

0

당신이 보내는 응용 프로그램을 제어 할 수 있습니까? 그렇다면 BinaryWriterNetworkStream을 감싸고을 사용하여 문자열의 길이와 문자열 자체를 보내는 보내는 응용 프로그램을 변경할 수 있습니다. 위의 수신 응용 프로그램에서 BinaryReaderNetworkStream을 입력하고 .ReadString()으로 전화를 걸면 스트림에서 길이를 읽은 다음 올바른 길이의 문자열을 읽습니다.

전송 응용 프로그램을 제어 할 수없는 경우 호출에서 반환을 확인할 수 있습니다. 스트림의 끝에 0이 반환되므로 전송 응용 프로그램에서 소켓을 닫아야합니다.

또한 stream.Read()은 요청한 바이트 수를 반환하는 것이 보장되지 않으므로 반환 할 수 없습니다. flag 변수는 실제로 bytesread이어야하므로이 bytesread 변수를 .GetString 메서드에 전달해야합니다.