2011-06-22 32 views
2

私はTCPサーバーを実装するための小さなアプリケーションを書いていましたが、C#.NETの初心者としてチュートリアルに従ったばかりです。その認可部分はうまくいきますが、チュートリアルを厳密に続行するために、認可が行われた後、tcpClient.Close()との接続が切断されます。.NET TCPサーバー接続の切断

もっと多くのパケットを待ち受けるためにこのコードを調整する必要がありますか?ほとんどのサーバーはX分後に接続を切断すると思うが、私はこのタイプのものにはまだ慣れていない。

// Starts the TCP RCON Server 
public void StartServer() 
{ 
    Console.WriteLine("RCON Server starting on Port: {0}", serverPort); 

    this.tcpListener = new TcpListener(IPAddress.Any, serverPort); 
    this.listenThread = new Thread(new ThreadStart(ListenForClients)); 
    this.listenThread.Start(); 

    Console.WriteLine("RCON Server has been Started."); 
} 

// Listen for Client Connections 
private void ListenForClients() 
{ 
    this.tcpListener.Start(); 

    while (true) 
    { 
     // blocks until a client has connected to the server 
     TcpClient client = this.tcpListener.AcceptTcpClient(); 

     // Create a thread for client communication 
     Thread clientThread = new Thread(new ParameterizedThreadStart(ReadClientPacket)); 
     clientThread.Start(client); 
    } 
} 

private void ReadClientPacket(object client) 
{ 
    TcpClient tcpClient = (TcpClient)client; 
    NetworkStream clientStream = tcpClient.GetStream(); 

    bool terminate = false; 

    while (!terminate) 
    { 
     try 
     { 
      int packetsize; 

      // Create a new Packet Object and fill out the data from the incoming TCP Packets 
      RCONPacket packet = new RCONPacket(); 

      using (BinaryReader reader = new BinaryReader(clientStream)) 
      { 
       // First Int32 is Packet Size 
       packetsize = reader.ReadInt32(); 

       packet.RequestId = reader.ReadInt32(); 
       packet.RconDataReceived = (RCONPacket.RCONDATA_rec)reader.ReadInt32(); 

       Console.WriteLine("Packet Size: {0} RequestID: {1} ServerData: {2}", packetsize, packet.RequestId, packet.RconDataReceived); 

       // Read first and second String in the Packet (UTF8 Null Terminated) 
       packet.String1 = ReadBytesString(reader); 
       packet.String2 = ReadBytesString(reader); 

       Console.WriteLine("String1: {0} String2: {1}", packet.String1, packet.String2); 

       switch (packet.RconDataReceived) 
       { 
        case RCONPacket.RCONDATA_rec.SERVERDATA_AUTH: 
        { 
         if (packet.String1 == "testpass") 
         { 
          Console.WriteLine("Password is Valid"); 
          ReplyAuthRequest(packet.RequestId, tcpClient, packet.String1); // Junk Packet 
          ReplyAuthRequest(packet.RequestId, tcpClient, packet.String1); 
         } 
         else 
         { 
          Console.WriteLine("Password is Invalid"); 
          ReplyAuthRequest(BAD_PASSWORD, tcpClient, packet.String1); // Junk Packet 
          ReplyAuthRequest(BAD_PASSWORD, tcpClient, packet.String1); 

          terminate = true; 
         } 

         break; 
        } 
        case RCONPacket.RCONDATA_rec.SERVERDATA_EXECCOMMAND: 
        { 
         Console.WriteLine("RCON Command Packet Received"); 
         ReplyExecCommand(packet.RequestId, tcpClient); 

         break; 
        } 
        default: 
        { 
         break; 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
      terminate = true; 
     } 
    } 

    tcpClient.Close(); 
} 

答えて

4

あなたが気付いた場合、あなたはbreak文がたくさんあります。私はあなたのプログラムの全体設計についてはっきりしていませんが、それらを削除してwhile(!terminated) { .. }のようなwhileループのboolean値のチェックを追加すると、アプリケーションがプログラムに終了を知らせたり、 terminatedtrueに設定するため、ループも終了します。 while(true)と言っているのは、breakが発生するまで永遠に続きます。その後whileループから壊れて、.Close()が呼び出されます。

+0

それは理にかなっていますが、基本的に私が休憩でやっていることではありません。ただそれをもっと読みやすくすることを除けば?私はあなたが私がやっていることのより良い考えを得るかもしれないようにコードを更新しました。私はこのプロトコルhttp://developer.valvesoftware.com/wiki/Source_RCON_Protocolをサーバとして実装しようとしています。私が問題に直面しているのは、たとえその休憩を取り除いても、最初のパケットの後にReadClientPacket()を停止していましたが、今度は「ストリームが読み込めませんでした」というエラーメッセージが表示されました。 –

+0

btw、私はあなたの答えをすぐにマークします。ちょっと開いたままにして、私が先に進みこの問題を解決できるかどうかを見たいと思っていました。良い答えをありがとう! –

+0

私はちょうどそれを考え出したと思う。私はちょうどwhileループとtcpClient.Close()を削除する必要がありますか?それは次のパケットが受信されたときに関数全体が再び呼び出されるようにするでしょうか? –

関連する問題