2011-08-17 3 views
2

서버에 대한 Tcp 연결을 유지하는 자체 포함 클래스를 만들려고합니다.TcpClient BottleNeck

TcpClient tcpClient; 
NetworkStream networkStream; 
BinaryReader mReader; 
BinaryWriter mWriter; 

을 그리고 다음 코드를 사용하여 초기화 :

나는 다음과 같은 클래스 변수를 사용하고 내가 읽기에 대한 차단 호출을 사용하고

tcpClient = new TcpClient(host, 443); 
networkStream = tcpClient.GetStream(); 
mReader = new BinaryReader(networkStream); 
mWriter = new BinaryWriter(networkStream); 

receiveMessage = new Thread(new ThreadStart(ReceiveMessages)); 
receiveMessage.Start(); 

. 서버에서 오는 각 패킷에는 정확한 패킷 크기를 정의하는 4 바이트 (int) 접두어가 붙습니다. 내가 바이트를 저장하는 List (Byte)를 가진 ByteBuffer라는 이름의 클래스를 사용하고 있습니다.이 클래스는 int 및 기타 형식을 ReadInt(), ReadString() 등, 서버 프로토콜에 따라. 참고로

private void ReceiveMessages() 
{ 
    while (tcpClient.Connected) 
    { 
     if (tcpClient.Available >= 4) 
     { 
      try 
      { 
       ByteBuffer message = new ByteBuffer(); 
       message.AddBytes(mReader.ReadBytes(4)); 
       int mSize = message.ReadInt(); 
       message.AddBytes(mReader.ReadBytes(mSize - 4)); 
       MessageProcessor.Process(message); 
      } 
      catch (Exception ex) 
      { 
       Print(ex.Message); 
      } 
     } 
     Thread.Sleep(1); 
    } 
    Print("Receiver thread terminated."); 
    Reconnect(); 
} 

에서, MessageProcessor 적절하게 서버에 패킷 정보를 살펴보고 응답 정적 클래스이다

여기 수신기 스레드이다.

내 문제는 연결 트래픽이 너무 높아지면 응답이 상당히 지연되기 시작한다는 것입니다. 내가 궁금 하네, 거기에 내가 TCP 연결이 우려만큼 잘못하고있는 거니? 대신 비동기 버전의 클래스를 작성해야합니까? C# List 개체가 너무 느리게 ByteBuffer에서 자주 사용됩니까?

이것은 실제로 네트워크 프로그래밍에서의 첫 번째 시도이므로 모든 조언은 매우 유용 할 것입니다.

감사합니다.

+0

기다립니다 ... 당신은 단지 BinaryReader를 mReader에서 바로 정수를 읽을 수없이? 왜 ByteBuffer 메시지가 필요합니까? BinaryReader doc : http://msdn.microsoft.com/en-us/library/system.io.binaryreader.aspx –

+0

서버가 빅 엔디안을 사용하고 있으며 BinaryReader가 리틀 엔디안을 사용한다고 생각합니다. 또는 다른 방법. 나는 어느 것을 기억할 수 없다. – jjw

+0

확인. 그렇다면, 당신이하고있는 일에 정말로 어떤 문제도 보이지 않습니다. 이 단일 스레드를 유지하려면 프로필러를 사용하여 속도 저하가 어디에서 발생하는지 파악하는 것이 좋습니다. 귀하의 MessageProcessor.프로세스 (메시지)는 약간의 처리 시간이 필요합니다. 멀티 스레딩을 권장합니다. –

답변

0

대신 비동기 처리로 전환하십시오. 스레드를 사용하고 Thread.Sleep은 악합니다.

Socket.BeginReceive에서 또는 귀하의 경우 NetworkStream.BeginRead

에서 당신은 또한 나의 새로운 라이브러리를 사용할 수 있습니다 그래서 가 불량 인에 Thread.sleep 제거처럼 당신의 ReceiveMessages 방법을 다시 것 http://blog.gauffin.org/2012/05/griffin-networking-a-somewhat-performant-networking-library-for-net/

1

합니다. 더 빠른 바이트 배열을 사용합니다.

마찬가지로 @jgauffin은 비동기 네트워크 코드가 훨씬 좋지만 엉망이되기 쉽습니다. 네트워크 프로그래밍으로 시작한다면 더 간단하게 유지하십시오.

이 기능이 잘 작동되기를 바랍니다.

참고 메시지는 4 바이트의 헤더

private void ReceiveMessages() 
    { 

     while (tcpClient.Connected) { 
      try { 

       var networkstream = tcpClient.GetStream(); 
       var header = new byte[4]; 
       networkstream.Read(header, 0, 4); 

       int len = 0; 
       // calculate length from header 
       // Do reverse for BigEndian, for little endian remove 
       Array.Reverse(header); 
       len = BitConverter.ToInt32(header, 0); 

       var message = new byte[len]; 
       networkstream.Read(message, 0, message.Length); 

       // Process message 

      } 
      catch (Exception ex) 
      { 
       Print(ex.Message); 
       // Exit loop something went wrong 
       break; 
      } 
     } 

     Print("Receiver thread terminated."); 
     Reconnect(); 

    } 
+0

해당 코드를 보내 주셔서 감사합니다. 가능한 한 빨리 시도해 보겠습니다. Thread.Sleep()이 없으면 프로그램이 CPU의 상당 부분을 사용했기 때문에 거기에 Thread.Sleep()이있었습니다. 이것을 피할 수있는 다른 방법이 있습니까? – jjw

+0

이 코드에서 networkstream.Read는 충분한 바이트가 사용 가능해질 때까지 차단합니다. Thread.Sleep이 필요 없습니다. –

+0

아, 사용 가능한 바이트를 확인하지 않으려 고합니다. 이것은 내가하는 일보다 훨씬 더 의미가 있습니다. 감사합니다 – jjw

관련 문제