どんなに複雑なTCPアプリケーションでは、両方の基本的な前提は、あなたがこれに基づいて、相互にデータを送受信することができます前に、クライアントとサーバー側の最初のTCP接続を通信することはありません。サーバは同時に複数のクライアントにサービスを提供する必要があるので、プログラムは比較的複雑であるため。のみ接続するサーバーを指定する必要があり、クライアントとサーバーの接続が比較的単純であり、サーバー側では、プログラマは、クライアントの接続要求かどうか、およびソケットを介して監視しているクライアントを区別するために引き続きプログラムを記述する必要があります。双方は、接続を確立し、対応するソケットを作成したら、お互いを送信し、データを受信することができます。プログラムでは、データを送受信する方法は同じであり、相違点のみ異なる方向にあります。
同期TCPアプリケーションのプログラミングでは、送信、受信およびステートメントの使用が動作するための方法をブロックしている監視します。同時TCP書き込み、サーバー側のプログラムを使用して一般的な手順は次のとおりです。
1)ネットワーク・タイプ、データ伝送タイプ及びプロトコルタイプを使用するローカルソケットオブジェクトを含むサーバのIPアドレスとポート番号を作成し、その結合。このプロセスは、SocketクラスまたはクラスのTcpListenerを経て完成することができます。
2)クライアント要求を受信するように接続された指定されたポート上で聞きます。
3)クライアントからの接続要求を受け付けると、クライアントから送信された接続情報に基づいて作成されたクライアントれるtcpClientソケットまたは複数のオブジェクトに対応します。
4)ソケットによるれるtcpClientオブジェクトまたは作成されたオブジェクトは、各クライアントとの各データ伝送接続。
5)送信条件に応じて互いに接続情報をクローズするかどうかを決定します。
一般手順クライアントを書き込むTCP同期を使用して:
1)を含む送信中に使用されるネットワーク・タイプ、データ伝送タイプ及びプロトコルタイプれるtcpClientソケットまたは複数のオブジェクトを作成します。
2)リモートサーバとの接続を確立するための方法を接続します。
3)サーバへのデータ送信のために。
4)作業が完了した後、サーバオフに情報を送信し、サーバへの接続を閉じます。
ソケットプログラミングとパッケージングの後に読者にれるtcpClientとTcpListener違いのアイデアを与えるために、ここでは簡単な紹介を行うためのプログラムで実装3つのキーコードです。
ソケットを使用してデータを送受信する1
ネットワークでは、データは、送信のためのバイトのストリームです。データ変換サーバとの接続を両端を確立するためにクライアント後、プログラムは最初に送信する必要があるバイト配列され、その後ソケットオブジェクトを使用してデータがメソッドを送信する送信、又は受信方法を使用してデータを受け取ります。送信されるバイトのアレイをリモートホストに直接送信されていないが、このマシンは、TCP送信バッファに送信されることに注意してください。同じトークンは、受信データが、即ち、プログラムデータがTCP受信バッファから受信される事実です。SendBufferSizeプロパティは、ソケットクラスの送信バッファサイズを取得または設定するために使用することができ、ReceiveBufferSizeプロパティを使用すると、受信バッファのサイズを取得または設定し、デフォルトのサイズを使用することができます。システムが要因が被写体に影響リモート・ホストにネットワークを介して送信されるデータをバッファリングする場合のように、プログラム中に考慮する必要はありません。
1.1サーバサイドのプログラミングキーコード
サーバー側のプログラムでは、送信のためのキーコードとソケットを使用してデータを受信します。
使用してSystem.Net; 使用してSystem.Net.Socketsを、 ...... ipadress IP = IPAdress.Prase(" サーバーのIPアドレスを" ); IPEndPoint IEP = 新新IPEndPoint(IP、使用可能なポート番号); ソケットソケット = 新しい新しいソケット(AdressFamily.InterNetwork 、SocketType.Stream、ProtocolType.Tcp); Socket.bind(IEP); socket.Listen(クライアント接続の最大数); ソケットclientSocket、 = socket.Accept(); ... // clientSocketによってクライアントにデータを送信し、 文字列メッセージ= " データを送信" ; バイト [] = sendbytesSystem.Text.Encoding.UTF8.GetBytes(メッセージ); INT successSendBytes = clientSocket.Send(sendbytes、sendbytes.Length、SocketFlags.None); ... // クライアントによって受信されたデータclientSocket着信 バイト [] = receivebytes 新しい新規の バイト [ 1024 ]; int型 successReceiveBytes = clientSocket.Receive(receivebytes)。
TCPはコネクション指向のプロトコルであるため、データを送信する前に、プログラムがこのIPアドレスとポート番号結合の最初のソケットは、リスニング状態でそれをしなければならないので、クライアントの接続要求を聞くことによって方法が受け入れた場合。、指定したポートでクライアントを識別するための接続情報を聞くためにと天然の結合;ソケットが使用されているプロトコルを示すために使用されているオブジェクトのメソッドを受け入れ、それはセットの互いのIPアドレスとポート番号を取得することである呼び出し情報ワードニーズにお問い合わせください。唯一の他の側面は、互いに通信するためにIPアドレスとポート番号の情報を取得しているため。プログラムが受け入れるメソッドを実行すると、それは次の文に進む前に、クライアント、サーバーに接続要求するまでブロックされた状態になります。受け入れサーバがクライアントに接続すると、この方法は、お互いのIPアドレスとポート番号の新しいクライアントの通信ソケットとに含まれたソケットを返す受け入れ、そしてソケットが使用して返すことができますクライアントが通信します。
整数メソッドが正常に送信されるバイトの数を示す値を返す送ります。我々はすぐに送信され、ネットワークに転送されますが、TCP送信バッファに転送されないデータとして、このセクションの冒頭で述べたように。ネットワークのTCP送信バッファへのデータの元の原因がネットワーク上で送信するための時間がなかった場合は、ブロックモードで、受信者が送信したバイトの数の全てを受信し続けることができなくなり、この方法は、実際に成功を返します。どのように多くのバイトは、TCP送信バッファに送られました。
ない場合は、ネットワーク上の理由から、我々は、データが一度、TCP送信バッファに配信されるすべてのためにできるようになることを保証することはできません。TCP送信バッファが再びデータを受け取ることができるので、これはあるデータは、送信するための方法を送信、つまり、それ自身の大きさに依存し、TCP送信バッファの実効値を超えた後、この方法は、送信するすべてのデータを呼び出すことができなくなります成功したキャッシュに送信されました。したがって、実際のプログラミングは、プログラムループを介して送信されるべきであり、すべてのデータが正常に送信されるまで、正常に送信されたバイト数を検出します。Sendメソッド送信されたデータは一度メソッドを送ると呼ばれるTCP送信バッファの実効値未満である場合はもちろん、すべて正常に送信できます。
伝送とは対照的に、受信方法は、TCP受信バッファからデータを受信する、受信方法は、値が表す実際に受信したバイトの整数を返し、リモートクライアントソケット接続が閉じられているが、この時間は、有効なデータがあった場合完全に受信され、受信方法は、値が0バイトで返します。
しかし、有効なデータがブロックモードで、TCP読めるバッファが受信されない場合、受信方法がブロックされることに注意することが一つのこと、しかし、非ブロックモードでは、受信方法がすぐに終了して、長袖をスローしますワード例外。これを避けるために、我々は、データが有効であるかどうかを検出するために、プロパティ利用可能な進歩を使用することができます利用可能な属性値が0でない場合は、その後、受信動作を再試行します。
キーコードのプログラミング1.2クライアント
クライアントのために、あなただけが接続が成功したら、あなたはサーバーとのソケット、キーコードを介して相互にデータを送信することができ、サーバとサーバ接続のIPアドレスとポート番号を作成する必要があります。
IP = IPAddress.ParseたIPAddress(" サーバーのIPアドレス" ); IPEndPoint IEP = 新新IPEndPoint(IP、サーバの待機ポート番号); ソケットServerSocketを = 新しい新しいソケット(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp); serverSocket.Connect (IEP); ... // ServerSocketを介してサーバにデータを送信 文字列メッセージ= " データ伝送" ; バイト [] = sendbytes System.Text.Encoding.UTF8.GetBytes(メッセージ); INT successSendBytes = serverSocket.Send(sendbytes、 sendbytes.Length、SocketFlags.None); ...... //受信したデータによってサーバから送信されたServerSocketを バイト [] = receivebytes 新しい新しい バイト [ 1024 ]; int型 successReceiveBytes = serverSocket.Receive(receivebytes)を、
目に見える、クライアントプログラム、データを送受信する方法と同様の方法では、データとの差分が作成され、サーバー側での使用の異なるソケットを送受信。
2送信したオブジェクトを使用してデータを受信NetworkStream
NetworkStreamは、ストリームデータを処理するために、ネットワークオブジェクトを捧げました。NetworkStreamオブジェクトを作成した後、オブジェクトデータを送信し、直接受信することができます。例えば:
= NetworkStream NetworkStream 新しい新しいNetworkStream(clientSocket); ... // データ送信 文字列メッセージ= " データ送信を" ; バイト [] = sendbytes System.Text.Encoding.UTF8.GetBytes(メッセージ); networkStream.Write(sendbytes、0 、 sendbytes.Length); ...... // データ受信 バイトを [] = readBytes 新しい新しい バイト [ 1024 ]; int型 I = networkStream.Read(readBytes、0、readbytes.Length)。
すべてのWriteメソッドは、TCP送信バッファにデータのバイト配列を確保しているため、それは、実際に送信されたバイト数を返しません、なぜ異なるソケットを持つメソッドを送信し、Writeメソッドは、空の戻り値をオブジェクトNetworkStream 、一度全て正常に送信され、ある程度のプログラミングの労力を簡素化したデータを送信することができないかもしれないSocketクラスを使用してsendメソッドを呼び出すときに発生する問題を回避することができます。しかし、このすべては、書き込み可能なプロパティの値が有効なオブジェクトをNetworkStream時に仕事のために動作している必要があり、その書き込み方法のNetworkStreamオブジェクトを使用する前に、書き込み可能なプロパティNetworkStreamオブジェクトをTrueにある、検出されます。
テキストの一行は、使用readlineおよびWriteLineメソッドメソッドStreamReaderクラスとStreamWriterクラス簡素後のオブジェクトNetworkStreamを作成するために、すべての情報を送信し、文字列と配列の間で変換するようにプログラムする必要はありません。場合
Writeメソッドとは、CanReadは、効果的なNetworkStreamオブジェクトを確保する前に読む方法のNetworkStreamクラス属性値呼び出しに対応します。この文脈において、プロセスは、一旦受信バッファ内のすべての有効なデータを変数に読み込まれ、正常に読み取られたバイト数を返します。
なお、それが可能であるため、読み取り方法はまた、整数戻り値を持つ理由は、TCP受信バッファは、他の側の指定された長さを介して送信されるデータを受信していません。言い換えれば、受信したデータは、その多くではないかもしれません。以下のページでは、我々はさらにこの問題を解決するための方法を検討します。
プロセスを読み込み一時Socketクラスと同様受信方法、リモートホストがソケット接続を閉じ、そしてこの時点で有効なデータが完全に受信された場合、すなわち、次に読むバイトの戻り値がゼロになります。
そして、クラス3れるtcpClient TcpListener
System.Net.Sockets名前空間、れるtcpClientクラスとTcpListenerクラス2クラスでのプログラミングTCPプロトコルに専用されています。両方のクラスは、それぞれ、下層のソケットをカプセル化し、プログラミングの難しさを低減するためにソケット、TCPアプリケーションをカプセル化する方法の同期および非同期動作を提供します。
クラスかどうかTcpListenerは、着信接続要求をリッスンし、データを、接続送受信するためれるtcpClientクラス。
3.1れるtcpClientクラス
れるtcpClientクラスは、System.Net名前空間の下に分類します。提供される方法を使用してれるtcpClientクラスは、ネットワークを介して接続することができる、ネットワークトラフィックを送受信します。4クラスのコンストラクタのオーバーロードがあります。
1)れるtcpClient()
デフォルトのコンストラクタが自動的にクライアントの未使用のIPアドレスとポート番号を選択するれるtcpClientオブジェクトを作成します。オブジェクトは、Connectメソッドを使用してサーバーとの接続を行うために作成された後。例えば:
れるtcpClientれるtcpClient = 新しいれるtcpClient(); tcpClient.Connect(" www.abcd.com "、51888);
2)れるtcpClient(AddressFamilyファミリー)
れるtcpClientコンストラクタも自動的にIPアドレスとクライアントのポート番号が使用されていない選択できるオブジェクトを作成しますが、AddressFamily列挙の使用は、使用するネットワークプロトコルを指定します。オブジェクトは、Connectメソッドを使用してサーバーとの接続を行うために作成された後。例えば:
れるtcpClientれるtcpClient = 新しいれるtcpClient(AddressFamily.InterNetwork)。 tcpClient.Connect(" www.abcd.com "、51888);
。3)れるtcpClient(IPEndPoint IEP)
IEP IPEndPointオブジェクトタイプ、IEPは、クライアントのIPアドレスとポート番号を指定します。クライアントホストが複数のIPアドレスを持っている場合は、このコンストラクタを使用するクライアントホストのIPアドレスを選択するために使用することができます。例えば:
たIPAddress []アドレス= Dns.GetHostAddresses(Dns.GetHostName())。 IPEndPoint IEP = 新しい IPEndPoint(アドレス[ 0 ]、51888 )。 れるtcpClientれるtcpClient = 新しいれるtcpClient(IEP)。 tcpClient.Connect(" www.abcd.com "、51888);
4)れるtcpClient(文字列のホスト名、int型ポート)
これは、コンフィギュレーション機能を使用するのが最も便利です。この設定機能は、直接が、接続方法を使用することなく、サーバのドメイン名とポート番号を指定することができます。クライアントホストのIPアドレスとポート番号が自動的に選択されます。例えば:
れるtcpClientれるtcpClient = 新しいれるtcpClient(" www.abcd.com "、51888);
表1と表2のリストの共通れるtcpClientクラスの属性とメソッド。
表1れるtcpClientクラスの共通プロパティ
プロパティ | 意味 |
クライアント | 根底にあるソケットを取得または設定します |
LingerState | 取得または設定し、ソケットに接続されたまま |
NODELAY | バッファを送信または受信する際の遅延を無効値が満杯でない取得または設定 |
ReceiveBufferSize | 受信バッファはTCPのサイズを取得または設定 |
ReceiveTimeoutという | 取得またはソケットがデータの受信タイムアウト設定 |
SendBufferSize | 送信バッファサイズはTCPを取得または設定 |
SendTimeout | 送信データソケットタイムアウトを取得または設定 |
表2れるtcpClientクラスの従来の方法
方法 | 意味 |
閉じる | 基になる接続を閉じずに、れるtcpClient例をリリース |
コネクト | 指定したホスト名とポート番号を持つクライアントは、TCPホストに接続します |
接続を開始 | リモートホスト接続を開始するための非同期リクエスト |
EndConnect | 非同期は、着信接続の試行を受け入れます |
GETSTREAM | NetworkStreamは、データの送受信が可能なオブジェクトを取得します |
3.2 TcpListenerクラス
TcpListenerクラスと受け取った着信接続要求をリスニング。クラスのコンストラクタは、次のとおりです。
1)TcpListener(IPEndPoint IEP)
前記IEP IPEndPointオブジェクトタイプ、IEPは、IPアドレスとサーバのポート番号を含みます。クライアントIPEndPointのタイプを聞くことによって、指定したIPアドレスとポートオブジェクトのコンストラクタ接続要求。
2)TcpListener(たIPAddress LocalAddrは、int型ポート)は
パラメータであり、着信接続要求をリッスンするローカルIPアドレスとポート番号を指定して直接ローカルIPアドレスとポートを指定するTcpListenerオブジェクトを確立します。
TcpListenerオブジェクトを構築したら、クライアントの接続要求を監視することができます。そして、同様のれるtcpClient、動作の同期モードで、それぞれ同期および非同期メソッドを提供TcpListenerは、対応する方法AcceptTcpClient、AcceptSocket法、開始および停止方法の方法が存在します。
オブジェクトを取得し、同期ブロッキングモードでデータを送受信するためのソケットを返すためAcceptSocket方法。ソケットはローカルとリモートホストのIPアドレスとポート番号を含み、そしてオブジェクトの送信および受信ソケット方式とリモートホストを呼び出すことで通信します。
パッケージを取得して戻すための方法は、同期モードブロッキングソケットれるtcpClientオブジェクトにデータを送受信するために使用することができるAcceptTcpClient。
リスナーを開始するために使用する方法を起動し、コンストラクタは以下のとおりです。
公共 のボイドスタート(int型のバックログ)
最大整数パラメータ要求バックログキューの長さ、クライアント接続の、すなわち最大許容数。Startメソッドが呼び出され、そして彼自身のLocalEndPoint基礎となるSocketオブジェクトが自動的に呼び出され、一緒に結合、およびSocketオブジェクトのメソッドを聞くためにした後、クライアントからの要求をリスニングを開始。あなたは、クライアントの要求を受け入れた場合、メソッドは自動的にリクエストキューに要求を入れ、その後、あなたが聞いて停止するにはStopメソッドを呼び出すまで、次の要求を監視していきます起動します。受信した要求の最大長はTcpListener要求キューを超え0以下である場合に、例外がスローされたリモートホストへの接続要求を待ちます。
リクエストのコンストラクタのリスニングを停止する方法を停止します。
公共 のボイドストップ()
プログラムの実行方法を停止し、すぐにクライアントの接続要求をリスニングを停止し、ソケットの基礎となるオブジェクトを閉じます。キューで待機している要求は例外ソケットをスローしますリモートホストの接続要求を受け入れるのを待って、失われます。
国境問題の4 NO TCPプロトコルメッセージングソリューションません
TCP通信プロトコルを使用している間、受信機は、送信者によって送信された順序でデータを受信することができるが、ネットワーク内の伝送は、一貫性のない送信者はメッセージ受信現象の受信者とメッセージを送信してもよいです。例:「12345」を送信するための第1の文字列データ送信側、第2の文字列データを送信すべき「ABCDE」であり、通常、受信者は最初に受信した文字列を受信する必要があります:「12345」 「ABCDE」:第二回受けました。
しかし、トランシーバは情報が非常に速い場合、受信側は受信した最後の可能性があるコンテンツが2またはコンテンツ送信を複数回受けて、すなわち、「12345abcde」です。
最も極端な場合には、受信者が送信者によって送信されたメッセージの受信に数回を経ることでもあります。「1234」の例えば最初の領収書、「45AB」である第3のような第二の「CDE」。
TCPプロトコルは、伝送ネットワークにおける不確実性へのバイトストリーム形式、無プロトコルメッセージの境界、であるため、個々のデータを単一の受信方法を送信する方法を送る読まれることを保証することはできませんので、これは主にです。
あなたが送信者によって送信されたコマンドを解析する必要がある場合、受信機は、エラーが発生した解決しないことを確実にするために、メッセージは、国境問題をプログラミングするとき、それ以外の場合は、失われたコマンド誤った結果を表示されることを考慮しなければなりません。例えば、二回送信されたメッセージの場合は、受信したコンテンツが、と劣らず、すべてを一度に受信していないが、コマンドを受信するたびに、プログラムで考慮されている場合は、論理的なエラーが発生し、別のコマンドを失うことになります。ネットワークのチェスプログラムと同様に、ステップを失った、すべての地獄の全体の論理が緩んで破りました。
実用化の方法は、TCPプロトコルメッセージの境界は次の3つの方法で問題を解決するには:
1)第一の方法は、固定長メッセージです。この方法は、固定長メッセージの場合にも適用可能です。
特定の実装では、オブジェクトは、例えば、ネットワークに各ストリームの固定長の送信データがBinaryReader System.IO空間と命名することができる、32ビット整数int型の各送信。BinaryReader BinaryWriterオブジェクトとオーバーロードされた種々の方法を提供し、固定長の種類が非常に便利であるデータを送受信します。
2)第二の方法は、メッセージの長さに沿ってメッセージを送信することです。たとえば、このメッセージの長さを示す4つのバイトは、メッセージは、メッセージの長さを含むことになる各送信されたメッセージの前にマシンはリモートホストに送信され、リモート・ホストが最初の4つのバイトからのメッセージ、最初のメッセージを受信した後メッセージの長さを取得し、受信したメッセージデータが周期的にメッセージの長さの値に応じて送信者によって送信されます。この方法は、あらゆる機会にも適用することができます。
BinaryReader BinaryWriterオブジェクトとオブジェクトも、このアプローチを実現するための最も便利な方法です。BinaryWriterオブジェクトは、あらゆる機会に適用することができ、オーバーロードWriteメソッドの数を提供します。ウェブに文字列を書き込む場合、例えば、本方法は、自動的に文字列によって占有されるバイトの数、文字列の前方に取り付けられた接頭辞として4バイトの文字列を計算し、受信者は、文字ReadStringを受信する方法を用いて文字列は、それが最初の文字列のプレフィックスとプレフィックス自動的に読み取られた文字列の文字列指定した長さを読み込むとき。
TCPプロトコルを使用して、バイナリファイルなどのバイナリストリームデータを、ネットワークを介して送信されている場合は、プログラムのコード長で計算機能を実装する必要があります。ネットワークデータの暗号化と復号化の本の章の例としては、国境問題は、この方法を使用することで解決するために、ネットワーク上で暗号化されたデータを転送します。
3)第三の方法は、特別なマーカーメッセージセパレータを使用することです。デリミタとして例えばCRLF(\ Rを\ n)のために。この方法は、主に、メッセージは特別なフラグが含まれない場合に用いられます。
文字列処理のために、これを達成するための最も便利な方法はのStreamWriterオブジェクトとStreamReaderオブジェクトです。送信者ごとのStreamWriterオブジェクトWriteLineメソッドは、書き込みネットワークフローの文字列を送信し、ReadLineメソッドごとの受信者は、文字列タグとして読み出されるネットワークからキャリッジリターンラインフィードストリームとStreamReaderオブジェクトを使用しますことができます。この章の例では、このメソッドを使用しています。
自分の長所と短所のメッセージ境界に対処するための3つの方法が、どのように悪い方法で良いものを言うことはできません。一つの好適な方法は、プログラミング中の実際の条件に応じて選択されるべきです。