2013-01-10 4 views
5

マルチスレッドのC#でTCPクライアント/リスナを使用するには?私は私のサーバーのために、このコードを書かれている

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Threading.Tasks; 
    using System.Net; 
    using System.Threading; 
    using System.Net.Sockets; 
    using System.IO; 


namespace ConsoleApplication1 
{ 
    class Program 
    { 
     private static bool terminate; 

     public static bool Terminate 
     { 
      get { return terminate; } 
     } 

     private static int clientNumber = 0; 
     private static TcpListener tcpListener; 

     static void Main(string[] args) 
     { 
      StartServer(); 
      Console.Read(); 
     } 

     private static void StartServer() 
     { 
      try 
      { 
       Console.WriteLine("Server starting..."); 
       tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 8000); 
       terminate = false; 
       tcpListener.Start(); 
       tcpListener.BeginAcceptTcpClient(ConnectionHandler, null); 
       Console.ReadLine(); 

      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
      finally 
      { 
       Console.WriteLine("Server stopping..."); 
       terminate = true; 
       if (tcpListener != null) 
       { 
        tcpListener.Stop(); 
       } 
      } 
     } 

     private static void ConnectionHandler(IAsyncResult result) 
     { 
      TcpClient client = null; 

      try 
      { 
       client = tcpListener.EndAcceptTcpClient(result); 
      } 
      catch (Exception) 
      { 
       return; 
      } 

      tcpListener.BeginAcceptTcpClient(ConnectionHandler, null); 

      if (client!=null) 
      { 
       Interlocked.Increment(ref clientNumber); 
       string clientName = clientNumber.ToString(); 
       new ClientHandler(client, clientName); 
      } 
     } 
    } 
} 


    class ClientHandler 
    { 
     private TcpClient client; 
     private string ID; 

     internal ClientHandler(TcpClient client, string ID) 
     { 
      this.client = client; 
      this.ID = ID; 
      Thread thread = new Thread(ProcessConnection); 
      thread.IsBackground = true; 
      thread.Start(); 
     } 

     private void ProcessConnection() 
     { 
      using (client) 
      { 
       using (BinaryReader reader=new BinaryReader(client.GetStream())) 
       { 
        if (reader.ReadString()==Responses.RequestConnect) 
        { 
          using (BinaryWriter writer=new BinaryWriter(client.GetStream())) 
          { 
           writer.Write(Responses.AcknowledgeOK); 
           Console.WriteLine("Client: "+ID); 
           string message = string.Empty; 
           while (message!=Responses.Disconnect) 
           { 
            try 
            { 
             message = reader.ReadString(); 
            } 
            catch 
            { 
             continue; 
            } 
            if (message==Responses.RequestData) 
            { 
             writer.Write("Data Command Received"); 
            } 
            else if (message==Responses.Disconnect) 
            { 
             Console.WriteLine("Client disconnected: "+ID); 
            } 
            else 
            { 
             Console.WriteLine("Unknown Command"); 
            } 
           } 
          } 
        } 
        else 
        { 
         Console.WriteLine("Unable to connect client: "+ID); 
        } 
       } 
      } 
     } 
    } 

    class Responses 
    { 
     public const string AcknowledgeOK = "OK"; 
     public const string AcknowledgeCancel = "Cancel"; 
     public const string Disconnect = "Bye"; 
     public const string RequestConnect = "Hello"; 
     public const string RequestData = "Data"; 
    } 

このコードは、マルチスレッドの方法でクライアント要求を聞きます。私はこのサーバに接続された異なるクライアントと、どのクライアントが切断していて、異なるコマンドを要求しているかを区別することはできません。

私のクライアントコードは次のとおりです。

private static void clietnRequest(string message,ref string response) 
{ 
    using (TcpClient client = new TcpClient()) 
    { 
     if (!client.Connected) 
     { 
      client.Connect(IPAddress.Parse("127.0.0.1"), 8000); 
      using (NetworkStream networkStream = client.GetStream()) 
      { 
       using (BinaryWriter writer = new BinaryWriter(networkStream)) 
       { 
        writer.Write(Responses.RequestConnect); 
        using (BinaryReader reader = new BinaryReader(networkStream)) 
        { 
         if (reader.ReadString() == Responses.AcknowledgeOK) 
         { 
          response = Responses.AcknowledgeOK; 

         } 
        } 
       } 
      } 
     } 
    } 
} 

コードのこの作品は、クライアントをサーバに接続しますが、私はもうメッセージを送信することができません。私はクライアントに接続している場合、彼はサーバーにコマンドを送信することができます私のアプリにしたい。これを行う代わりに、毎回サーバーへの新しいクライアントとして機能します。私はここでいくつかのものを逃している、親切に正しい方向に私を導く。私はC#のネットワーキングプログラミングに全く新しいです。親切にコードを改善するのに役立ちます。 Tcp ListenerとTcp Clientはこのシナリオで有効ですか、ソケットを使用する必要がありますか?

+0

例外を「リターン」で飲み込むだけでは何かが間違っているかどうかわからないはずです。少なくともロギングの形式を取ってください。 –

+0

デモの目的のためだけに、 – user1941098

+0

これはまだ早期に壊れるのが良い悪い習慣です。別のメモで、返り値としてレスポンスを渡すのではなく、なぜ 'ref'を使用していますか? –

答えて

3

メッセージを送信した後にクライアント側で接続を終了していますが、何も問題がないようにしたい場合は、サーバーに何らかの形式のIDを送信する必要があります。新しい接続ではなく、もう一度接続する古い接続です。これは正確にHTTPプロトコルがやっていることであり、 "識別"はインターネットクッキーです。

非常にまれにデータを送信すると最初のオプションは問題ありませんが、頻繁に行う場合は、接続を開いたままにする必要があります。

基本的には、クライアント要求関数の接続と切断、および引数としてのオープン接続の引き渡しを行う必要があります。このようclientオブジェクトサーバ側がクライアントを表し、あなたが接続されたクライアントごとに、それの1つのインスタンスを持つことになりますし、彼が切断されるまで、そのクライアントに関連付けられたままになり、それを行うことによって

private void MainCode() 
{ 
    using (TcpClient client = new TcpClient()) 
    { 
     client.Connect(IPAddress.Parse("127.0.0.1"), 8000); 

     while(variableThatRepresentsRunning) 
     { 
      //(Snip logic that gererates the message) 

      clietnRequest(message, ref response, client); 

      //(Snip more logic) 
     } 
    } 
} 

private static void clietnRequest(string message,ref string response, TcpClient client) 
{ 
    if (client.Connected) 
    { 
     using (NetworkStream networkStream = client.GetStream()) 
     { 
      using (BinaryWriter writer = new BinaryWriter(networkStream)) 
      { 
       writer.Write(Responses.RequestConnect); 
       using (BinaryReader reader = new BinaryReader(networkStream)) 
       { 
        if (reader.ReadString() == Responses.AcknowledgeOK) 
        { 
         response = Responses.AcknowledgeOK; 

        } 
       } 
      } 
     } 
    } 
    else 
    { 
     //Show some error because the client was not connected 
    } 
} 

。接続されたすべてのクライアントを追跡する場合は、(Concurrent Collectionを使用するか、マルチスレッドのためにロックを使用する)のようなコレクションにすべてを挿入してから、すべてのクライアントのリストを取得する必要があります切断後にクライアントがリストから削除されるように、クライアントは後でクリーンアップする必要があります)。

+0

私は、どこからクライアントを渡すのだろうと思っていますパラメータをclientRequestメソッドに設定しますか? – user1941098

+0

私は 'clientRequest'が何らかの形のループの中から呼び出されたと仮定しています。ループの前に接続を作成し、ループの終了後に接続を閉じます。 –