2011-05-03 2 views
4

다시 한 번이 문제를 파악하는 데 도움이 필요합니다. 이미 하루가 지나고 코드와 출력에서이 문제가 발생하는 이유를 알 수없는 것 같습니다.C#에서 RCON 프로토콜 구현에 관한 문제를 일으킬 수 있습니다.

좋아 ..... 그래서 기본적으로 지금까지 내가 얻고, C#으로 밸브의 RCON Protocol을 구현하기 위해 애 쓰고 expected output 아래의 코드와 샘플 사용 주어진 :

사용법 :

RconExec(socket, "cvarlist"); 

코드 :

private string RconExec(Socket sock, string command) 
{ 
    if (!sock.Connected) throw new Exception("Not connected"); 

    //sock.DontFragment = true; 
    sock.ReceiveTimeout = 10000; 
    sock.SendTimeout = 10000; 
    //sock.Blocking = true; 

    Debug.WriteLine("Executing RCON Command: " + command); 

    byte[] rconCmdPacket = GetRconCmdPacket(command); 
    sock.Send(rconCmdPacket); //Send the request packet 
    sock.Send(GetRconCmdPacket("echo END")); //This is the last response to be received from the server to indicate the end of receiving process 
    RconPacket rconCmdResponsePacket = null; 

    string data = null; 

    StringBuilder cmdResponse = new StringBuilder(); 

    RconPacket packet = null; 
    int totalBytesRead = 0; 

    do 
    { 
     byte[] buffer = new byte[4]; //Allocate buffer for the packet size field 
     int bytesReceived = sock.Receive(buffer); //Read the first 4 bytes to determine the packet size 
     int packetSize = BitConverter.ToInt32(buffer, 0); //Get the packet size 

     //Now proceed with the rest of the data 
     byte[] responseBuffer = new byte[packetSize]; 

     //Receive more data from server 
     int bytesRead = sock.Receive(responseBuffer); 

     //Parse the packet by wrapping under RconPacket class 
     packet = new RconPacket(responseBuffer); 
     totalBytesRead += packet.String1.Length; 

     string response = packet.String1; 
     cmdResponse.Append(packet.String1); 

     Debug.WriteLine(response); 

     Thread.Sleep(50); 

    } while (!packet.String1.Substring(0,3).Equals("END")); 

    Debug.WriteLine("DONE..Exited the Loop"); 
    Debug.WriteLine("Bytes Read: " + totalBytesRead + ", Buffer Length: " + cmdResponse.Length); 

    sock.Disconnect(true); 

    return ""; 
} 

문제점 :

디버그 창에서 출력을 테스트 중이므로 아직 최종 코드가 아닙니다. 코드를 실제 상태로 수정하면 몇 가지 문제가 발생합니다.

  1. 내가 Thread.Sleep(50) 제거하면 Thread.Sleep(50)

    • 제거, 출력이 완료되지 않습니다 예외를 던지는 끝납니다. 나는 'END'종료 문자열이 서버에 의해 미리 성숙하게 전송된다는 것을 알아 차렸다. 이 문자열은 전체 목록이 완료 될 때만 서버에서 보내질 것으로 예상됩니다. Exception Thrown 나는이 많은 시간을 시험하고 똑같은 일이 일어난다. 나는 그 줄을 제거하지 않으면 목록이 완성되고 함수가 루프를 적절하게 빠져 나온다.
  2. 루프 내의 Debug.WriteLine(response); 분리 루프 밖에서 Debug.WriteLine(cmdResponse.ToString());를 사용하여 문자열을 출력하는 부분적인 목록 데이터가 표시된다. 루프에서 읽은 실제 바이트를 StringBuilder 인스턴스의 길이와 비교해도 동일합니다. 생성 된 출력에 대해 here을 클릭하십시오.

왜 위에서 언급 한 두 가지 시나리오가 발생합니까?

답변

3

Socket.Receive은 제공된 버퍼의 길이보다 적은 바이트를 읽을 수 있다고 생각하지 않습니다. 반환 값은 실제로 읽은 바이트 수를 알려줍니다. 이 값을 변수에 제대로 저장하고있는 것을 볼 수 있지만 사용하는 코드를 볼 수 없습니다.

전체 패키지를 검색하려면 Receive 번을 몇 번 호출 할 준비가되어 있어야합니다. 특히 패키지 데이터를받을 때.

나는 이것이 귀하의 문제의 원인인지 확신하지 못합니다. 하지만 클라이언트 측에서 짧은 지연만으로 네트워크 버퍼를 채우기에 충분할 수 있으므로 전체 패키지가 단일 호출로 읽혀지기 때문에 가능할 수 있습니다.

패키지 데이터를 검색하기 위해 다음 코드를 사용해보십시오 :

int bufferPos = 0; 
while (bufferPos < responseBuffer.Length) 
{ 
    bufferPos += socket.Receive(responseBuffer, bufferPos, responseBuffer.Length - bufferPos, SocketFlags.None); 
} 

참고 : Receive의 최초의 호출 (패키지의 데이터 길이를받는 사람이) 반환하지 않는 경우에도 케이스를 지원해야 4 바이트.

+0

제안 해 주셔서 감사합니다. 나는 수신 방법에 넣은 크기가 단일 호출을 통해 서버에서 전송할 것으로 예상되는 바이트 수임을 전제로 오해되었습니다. 받은 바이트 수를 확인하는 데 신경 쓰지도 않았다. 나는 집에 돌아갈 때 이것을 시도 할 것이다. 다시 한 번 감사드립니다! –

+0

업데이트 : 문제 해결 :) 감사합니다. 나는 이것을 계속 염두에두고 앞으로 나아갈 것이다. –

관련 문제