c#ネットワークプログラミングtcpListenerとtcpClientを使用
15430 ワード
引用:http://ilewen.com/questions/514
このチュートリアルでは、C#でスレッド内のTCPサービス・エンドを構築する方法を説明します.Windowsのsocketsでプログラムを書いたことがあるなら、どれだけ面倒なのか知っています.ありがとう.netフレームワークは、ネットワークプログラミングを容易にしました.
クライアント接続を受け入れ、データを送信および受信できる非常に簡単なサーバを構築します.サーバは、接続クライアントごとにスレッドを生成し、理論的には複数の接続を受け入れることができます(実際にはWindowsには制限がありますが).コードを次に示します.
基本的なサーバクラスが構築されています.TcpListener変数(TcpListenerは下位ソケット通信動作をカプセル化する)を定義し,クライアントの接続を傍受するためのスレッドを定義した.次に、ThreadStartの委任関数であるListenForClientsを定義します.コードは次のとおりです.
この関数はとても簡単です.まず、TcpListenerを起動し、接続をループします.AccepttTcpClientの呼び出しは、クライアント接続までスレッドの実行をブロックします.ここでは、新しいクライアントとの通信を処理するためにスレッドをトリガーします.ParameterizedThreadStart依頼を使用したので、AccepttTcpClient呼び出しで返されたTcpClientオブジェクトを新しいスレッドに渡すことができます.
ParameterizedThreadStartは関数HandleClientCommを使用します.この関数はクライアントからデータを読み出す役割を果たします.それを見てみましょう.
最初のステップでは、ParameterizedThreadStart依頼は基本オブジェクトタイプのみを受け入れるため、クライアントタイプをTcpClientタイプに変換します.次に、TcpClientからNetworkStreamを取得してデータを読み込む.その後、whileループを介してクライアントからデータを読み出す.read呼び出しは、クライアントからデータを受信するまでブロックされた状態になります.クライアントからゼロバイトに読み込まれた場合は、クライアントが切断されていることを示します.この例では、文字列をバイト配列に変換し、コンソールに出力するだけです.もちろん、もっと複雑な仕事をします.ソケットにエラーが発生したり、クライアントが接続を切断したりした場合は、TcpClientオブジェクトのclose関数を呼び出して接続を閉じ、使用するリソースを解放する必要があります.
サーバスレッドを作成し、接続を受け入れ、クライアントからデータを読み出すために必要なすべてのことです.もちろん、サービス側がデータを送信できない場合は、何の役にも立たない.次に、接続されているクライアントにデータを送信する方法を見てみましょう.
AccepttTcpClientから返されたTcpClientオブジェクトは、クライアントにデータを送信するために使用されます.したがって、これらのオブジェクトはサービス側に保存する必要があります.通常、TcpClientオブジェクトのセットを作成できます.データの送信は非常に簡単で、clientのNetworkStreamオブジェクトを取得し、writeメソッドを呼び出すだけでいいです.
TCPサービスは完了しました.難しい部分は、クライアントとサービス側の間で情報を送信するためのプロトコルを定義することです.アプリケーション層のプロトコルは、通常、異なるアプリケーションに対して異なる.だから私はもっと説明するつもりはありません.あなたは自分のことを実現するだけです.
クライアントがサービス側に接続されていない場合、このサービス側はまだ存在する意味がありますか?このチュートリアルでは、主にサービス側のプログラミングについて説明しますが、基本的なTCP接続を設定し、データを送信する方法について説明する短いコードがあります.
最初のステップは、クライアントからサービス側への接続を取得することです.TcpClient.Connectメソッドを使用します.サービス側のIPEndPointを知る必要があります.ここでは、ローカルホスト、ポート番号3000に接続します.文字列「hello Server!」を送信します.
注:クライアントまたはサーバからの書き込みは、必ずしも受信側で読むものではありません.たとえば、クライアントはサーバに10バイトを送信しますが、サーバは最初の読み取りで10バイトすべてを取得できない場合があります.TCPを使用すると、最終的に10バイトすべてが得られることはほぼ保証されますが、1回以上読み込む必要がある場合があります.インタラクティブプロトコルを設計するときは、この点に注意してください.
このチュートリアルでは、C#でスレッド内のTCPサービス・エンドを構築する方法を説明します.Windowsのsocketsでプログラムを書いたことがあるなら、どれだけ面倒なのか知っています.ありがとう.netフレームワークは、ネットワークプログラミングを容易にしました.
クライアント接続を受け入れ、データを送信および受信できる非常に簡単なサーバを構築します.サーバは、接続クライアントごとにスレッドを生成し、理論的には複数の接続を受け入れることができます(実際にはWindowsには制限がありますが).コードを次に示します.
using System; using System.Text; using System.Net.Sockets; using System.Threading; using System.Net; namespace TCPServerTutorial { class Server { private TcpListener tcpListener; private Thread listenThread; public Server() { this.tcpListener = new TcpListener(IPAddress.Any, 3000); this.listenThread = new Thread(new ThreadStart(ListenForClients)); this.listenThread.Start(); } } }
基本的なサーバクラスが構築されています.TcpListener変数(TcpListenerは下位ソケット通信動作をカプセル化する)を定義し,クライアントの接続を傍受するためのスレッドを定義した.次に、ThreadStartの委任関数であるListenForClientsを定義します.コードは次のとおりです.
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 to handle communication //with connected client Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm)); clientThread.Start(client); } }
この関数はとても簡単です.まず、TcpListenerを起動し、接続をループします.AccepttTcpClientの呼び出しは、クライアント接続までスレッドの実行をブロックします.ここでは、新しいクライアントとの通信を処理するためにスレッドをトリガーします.ParameterizedThreadStart依頼を使用したので、AccepttTcpClient呼び出しで返されたTcpClientオブジェクトを新しいスレッドに渡すことができます.
ParameterizedThreadStartは関数HandleClientCommを使用します.この関数はクライアントからデータを読み出す役割を果たします.それを見てみましょう.
private void HandleClientComm(object client) { TcpClient tcpClient = (TcpClient)client; NetworkStream clientStream = tcpClient.GetStream(); byte[] message = new byte[4096]; int bytesRead; while (true) { bytesRead = 0; try { //blocks until a client sends a message bytesRead = clientStream.Read(message, 0, 4096); } catch { //a socket error has occured break; } if (bytesRead == 0) { //the client has disconnected from the server break; } //message has successfully been received ASCIIEncoding encoder = new ASCIIEncoding(); System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead)); } tcpClient.Close(); }
最初のステップでは、ParameterizedThreadStart依頼は基本オブジェクトタイプのみを受け入れるため、クライアントタイプをTcpClientタイプに変換します.次に、TcpClientからNetworkStreamを取得してデータを読み込む.その後、whileループを介してクライアントからデータを読み出す.read呼び出しは、クライアントからデータを受信するまでブロックされた状態になります.クライアントからゼロバイトに読み込まれた場合は、クライアントが切断されていることを示します.この例では、文字列をバイト配列に変換し、コンソールに出力するだけです.もちろん、もっと複雑な仕事をします.ソケットにエラーが発生したり、クライアントが接続を切断したりした場合は、TcpClientオブジェクトのclose関数を呼び出して接続を閉じ、使用するリソースを解放する必要があります.
サーバスレッドを作成し、接続を受け入れ、クライアントからデータを読み出すために必要なすべてのことです.もちろん、サービス側がデータを送信できない場合は、何の役にも立たない.次に、接続されているクライアントにデータを送信する方法を見てみましょう.
NetworkStream clientStream = tcpClient.GetStream(); ASCIIEncoding encoder = new ASCIIEncoding(); byte[] buffer = encoder.GetBytes("Hello Client!"); clientStream.Write(buffer, 0 , buffer.Length); clientStream.Flush();
AccepttTcpClientから返されたTcpClientオブジェクトは、クライアントにデータを送信するために使用されます.したがって、これらのオブジェクトはサービス側に保存する必要があります.通常、TcpClientオブジェクトのセットを作成できます.データの送信は非常に簡単で、clientのNetworkStreamオブジェクトを取得し、writeメソッドを呼び出すだけでいいです.
TCPサービスは完了しました.難しい部分は、クライアントとサービス側の間で情報を送信するためのプロトコルを定義することです.アプリケーション層のプロトコルは、通常、異なるアプリケーションに対して異なる.だから私はもっと説明するつもりはありません.あなたは自分のことを実現するだけです.
クライアントがサービス側に接続されていない場合、このサービス側はまだ存在する意味がありますか?このチュートリアルでは、主にサービス側のプログラミングについて説明しますが、基本的なTCP接続を設定し、データを送信する方法について説明する短いコードがあります.
TcpClient client = new TcpClient(); IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000); client.Connect(serverEndPoint); NetworkStream clientStream = client.GetStream(); ASCIIEncoding encoder = new ASCIIEncoding(); byte[] buffer = encoder.GetBytes("Hello Server!"); clientStream.Write(buffer, 0 , buffer.Length); clientStream.Flush();
最初のステップは、クライアントからサービス側への接続を取得することです.TcpClient.Connectメソッドを使用します.サービス側のIPEndPointを知る必要があります.ここでは、ローカルホスト、ポート番号3000に接続します.文字列「hello Server!」を送信します.
注:クライアントまたはサーバからの書き込みは、必ずしも受信側で読むものではありません.たとえば、クライアントはサーバに10バイトを送信しますが、サーバは最初の読み取りで10バイトすべてを取得できない場合があります.TCPを使用すると、最終的に10バイトすべてが得られることはほぼ保証されますが、1回以上読み込む必要がある場合があります.インタラクティブプロトコルを設計するときは、この点に注意してください.