2016-09-29 2 views
0

나의 현재 ClientHandler 방법은 NetStream에이 클라이언트 말했다 열어하는 TcpClient을 수신하고 이런 식으로 데이터를 당겨 시작합니다TcpClient/TcpListener를 사용하면 알 수없는 양의 개별 메시지를받는 가장 좋은 방법은 무엇입니까?

   try 
      { 
       //byte[] bytes = new byte[client.ReceiveBufferSize]; 
       byte[] bytes = new byte[100]; 
       int bytes_read = netstream.Read(bytes, 0, bytes.Length); 
       Console.WriteLine(DateTime.Now.ToString() + ": Bytes Read"); 

       while (bytes_read > 0) 
       { 
        memstream.Write(bytes, 0, bytes_read); 
        bytes_read = netstream.Read(bytes, 0, bytes.Length); 

        if (memstream.Length > 255) 
        { 
         MemStreamRead(memstream); 
         memstream.Flush(); 
         OkResponse(netstream); 
        } 
       } 
      } 

      catch (Exception e) 
      { 
       Console.WriteLine("No longer connected"); 
       connected = false; 
       Console.WriteLine(e); 
       Console.WriteLine(e.StackTrace); 
      } 

이미 클라이언트에서 첫 번째 메시지를 얻을 수 있습니다,하지만 난 힘든 시간을 어떻게 새 메시지에 대한 스트림을 열어두고, 내 현재 메시지가 완료되었는지 결정할 생각.

netstream.DataAvailable이 작동하는 것 같습니다. netstream이 더 이상 데이터를 가져 오지 않을 때이를 감지하고 false를 반환한다고 가정합니다. 그러나 새로운 데이터를 사용할 수있게되면 어떻게 다시 듣기 시작합니까?

미리 도움을 청하십시오!

+0

비동기 작업을 streamreader와 함께 사용하여 tcpclient의 기본 스트림 객체를 계속 읽을 수 있습니다. –

답변

2

TcpClient 개체와 해당 netstream을 반복해서 사용할 수 있습니다. 그런 다음 필요에 따라 자주 netstream.Read() (차단되지 않음)으로 전화하십시오. DataAvailable은 읽을 데이터가있는 경우 알려줍니다.

알림 : 들어오는 TCP 데이터는 큰 버퍼에 추가되며 패킷이 수신되면이를 다시 패킷으로 분리 할 수 ​​없습니다.
충분한 크기의 Read()을 호출하면 버퍼에서 '모든'데이터를 가져옵니다.
별도의 상위 프로토콜이 필요합니다. 쉽게 구현할 수 있습니다 ...

UDP에서는 반면에 Read()은 1 패킷의 데이터를 반환합니다. Read() 다음 s는 다음 패킷의 데이터를 리턴합니다. 패킷 방식의 '구조'는 유지됩니다. 는 TCP 높은 수준의 프로토콜의

, 당신은 할 수 :

  • 시작 각각의 메시지 (당신의 정의에 따라 메시지, 1 바이트 길이가 100.000 바이트를 가질 수) 1 개를 0xFF 바이트, 따라서 메시지 시작을 쉽게 감지 할 수 있습니다.
  • 0x02 (STX, 의미는 'Start of text')로 시작하고 0x03 (ETX, 텍스트 끝)으로 끝내십시오. 따라서 둘러싸여 있지 않은 '말도 안되는'데이터 (예 : 살아있는 메시지)는 제외 할 수 있습니다. STX, ETX.
  • 0x02, 0x03, 0xFF가 포함될 수있는 이진 데이터를 보내는 경우 숫자 인 nnnnnn을 사용하여 각 메시지를 시작할 수 있으며 메시지 길이를 바이트 단위로 정의 할 수 있습니다. 말도 안되는 데이터는 여기에서 분리 할 수 ​​없습니다.

편집 :
추가 통보 : 연결은 원격 측에 의해 폐쇄
경우 Read() 여전히 정상적으로 실행하지만, 데이터를 반환 할 것이다. 연결이 닫힐 지 여부를 다른 방법으로 찾아야합니다. 보다 유용한 정보를 얻으려면 다른 SO 네트워킹 관련 질문에 대한 답변을 참조하십시오.

+1

TCP로 '.Read'를 호출해도 패킷의 * part * 만 얻을 수 있음을 언급 할 수 있습니다. 때로는 완벽한 메시지를 얻기 위해 여러 개의'.Read'를해야 할 때가 있습니다. –

+0

@Bradley Uffner : 매우 드뭅니다. 패킷 단편화는 더 이상 자주 발생하지 않으며 afaik는 MTU가 보통 1500 바이트이지만 일반적으로 전송 된 데이터가 10KB와 같이 많이 MTU를 초과하더라도 NIC의 입력 버퍼에서 불완전한 패킷을 검색하지는 않습니다. TCP 계층은이를 전달하기 전에 다시 구성해야합니다. –

1

새 데이터를 사용할 수있게되면 어떻게 다시 듣기 시작합니까?

Read으로 다시 전화하십시오. 이것은 대부분의 루프가 작동하는 방식이며, 단순히 비 차단 (non-blocking) 인 Read (또는 전용 스레드의 블록 Read)을 호출하고 데이터를 받으면이를 처리합니다.

은 내 현재의 메시지는 당신이 가진 또 다른 문제입니다

을 수행 할 때. OS 소켓 버퍼에 더 이상 데이터가 없을 때 메시지가 반드시 완료되는 것은 아닙니다. 규칙에 따라 정의 된대로 처리됩니다. 일반적으로 메시지 길이로 메시지를 연 다음 지정된 길이의 버퍼를 채울 때까지 (또는 제한 시간으로 인해 실패 할 때까지) OS에 데이터를 계속 요청합니다.

관련 문제