このチュートリアルは、java I/Oの基本機能を示す簡単なクライアント-サーバーの例から始まり、javaにおけるソケットプログラミングの概要です。
java.io
パッケージと、Java1.4で導入されたノンブロッキングI/O(java.nio
)Apiの両方について紹介します。 最後に、NioでJava7以降から実装されたJavaネットワーキングを示す例を見ることができます。2.,
ソケットプログラミングは、互いに通信する二つのシステムに集約されます。 一般に、ネットワーク通信には、Transport Control Protocol(TCP)とUser Datagram Protocol(UDP)の二つのフレーバーがあります。 TCPとUDPは異なる目的で使用され、どちらも一意の制約があります。
- TCPは、クライアントがサーバと通信するための二つのシステムに接続することを可能にする比較的単純で信頼性の高いプロトコルです。 TCPでは、各エンティティはその通信ペイロードが受信されたことを認識します。,
- UDPはコネクションレスプロトコルであり、メディアストリーミングなど、すべてのパケットが宛先に到着する必要がないシナリオに適しています。
TCPとUDPの違いを理解するために、お気に入りのウェブサイトからビデオをストリーミングしていて、フレームを落とした場合にどうなるか するとともに、顧客ダ映画を受け、フレームやお好みの動画アップグレードどん? ビデオストリーミングプロトコ, TCPは配信を保証するため、HTTP、FTP、SMTP、POP3などに選択されるプロトコルです。
このチュートリアルでは、javaでのソケットプログラミングについて紹介します。 オリジナルのJava I/Oフレームワークの機能を示す一連のクライアント-サーバーの例を示し、徐々にNIOで導入された機能を使用するように進めます。2.
古い学校のJavaソケット
NIOより前の実装では、Java TCPクライアントソケットコードはjava.net.Socket
クラスによって処理されます。, 次のコードは、サーバーへの接続を開きます。
Socket socket = new Socket( server, port );
socket
インスタンスがサーバーに接続されると、サーバーへの入出力ストリームの取得を開始できます。 入力ストリームを読み込むために使用します。からのデータはサーバが出力ストリームを書き込むのに使用されるデータはサーバー通信を行います。, 次のメソッドを実行して入力ストリームと出力ストリームを取得できます。
InputStream in = socket.getInputStream();OutputStream out = socket.getOutputStream();
これらは通常のストリームであり、ファイルの読み取りと書き込みに使用するのと同じストリームであるため、ユースケースに最適な形式に変換することができます。 たとえば、OutputStream
をPrintStream
ラップして、println()
ようなメソッドでテキストを簡単に書くことができます。, 別の例として、InputStream
をBufferedReader
、InputStreamReader
ようなメソッドでテキストを簡単に読み取るためにreadLine()
。
Javaソケットクライアントの例
HTTPサーバーに対してHTTP GETを実行する短い例を見てみましょう。, HTTPはこの例で許可されているよりも洗練されていますが、サーバーからリソースを要求すると、サーバーが応答を返してストリームを閉じるという最も単純なケース この場合、次の手順が必要です。
- ポート80でリッスンしているwebサーバーへのソケットを作成します。
-
PrintStream
をサーバーに取得し、リクエストGET PATH HTTP/1.0
を送信します。PATH
はサーバー上で要求されたリソースです。, たとえば、webサイトのルートを開く場合、パスは/
になります。サーバーにInputStream
を取得し、それをBufferedReader
でラップし、レスポンスを行ごとに読み取ります。
リスト1に、この例のソース-コードを示します。
リスト1. SimpleSocketClientExample。java
リスト1には、接続するサーバー(ポート80でサーバーに接続していると仮定します)と取得するリソースの二つのコマンドライン引数を受け入れます。, サーバーを指し、明示的にポートを指定するSocket
を作成します80
。 次に、コマンドを実行します。
GET PATH HTTP/1.0
例えば、
GET / HTTP/1.0
何が起こったのですか?
などのwebサーバーからwebページを取得すると、HTTPクライアントはDNSサーバーを使用してサーバーのアドレスを検索します。
com
権限のあるドメインネームサーバーがドメインのトップレベルドメインサーバーに要求することから始まります。, 次に、
のIPアドレス(またはアドレス)をドメインネームサーバーに要求します。 次に、ポート80でそのサーバーへのソケットを開きます。 (または、別のポートを定義する場合は、
:8080
のように、コロンの後にポート番号を追加することで、それを行うことができます。 最後に、HTTPクライアントは、GET
、POST
、PUT
、DELETE
、HEAD
、OPTI/ONS
などの指定されたHTTPメソッドを実行します。 各メソッドには独自の構文があります。, 上記のコードsnipsに示されているように、GET
メソッドには、HTTP/version number
が続くパスと空の行が必要です。 HTTPヘッダーを追加したい場合は、新しい行を入力する前にそうすることができます。
リスト1では、OutputStream
を取得し、PrintStream
でラップして、テキストベースのコマンドをより簡単に実行できるようにしました。, 私たちのコードはInputStream
を取得し、それをInputStreamReader
でラップし、それをReader
に変換し、それをBufferedReader
。 PrintStream
を使用してGET
メソッドを実行し、次にBufferedReader
を使用して、null
応答を受け取るまで、ソケットが閉じられていたことを示す応答を行ごとに読み取ります。,
このクラスを実行し、次の引数を渡します。
java com.geekcap.javaworld.simplesocketclient.SimpleSocketClientExample www.javaworld.com /
以下のような出力が表示されます。
この出力はJavaWorldのwebサイトにテストページを表示します。
この出力は、JavaWorldのwebサイトにあるテストページを表示します。
この出力は、JavaWorld それはHTTPバージョン1.1を話し、応答は200 OK
であることを返しました。
Javaソケットサーバーの例
クライアント側について説明しましたが、幸いなことに、サーバー側の通信の側面も同じように簡単です。, 単純な観点からは、プロセスは次のとおりです。
- リッスンするポートを指定して
ServerSocket
を作成します。 -
ServerSocket
のaccept()
メソッドを呼び出して、クライアント接続用に構成されたポートをリッスンします。 - クライアントがサーバーに接続すると、
accept()
メソッドはSocket
を返し、サーバーがクライアントと通信できます。, これは、クライアントに使用したSocket
クラスと同じであるため、プロセスは同じです。InputStream
クライアントから読み取り、OutputStream
クライアントに書き込みます。サーバーをスケーラブルにする必要がある場合は、Socket
を別のスレッドに渡して処理し、サーバーが追加の接続をリッスンし続けることがで - 別の接続をリッスンするには、
ServerSocket
のaccept()
メソッドを再度呼び出します。,
すぐにわかるように、NIOのこのシナリオの処理は少し異なります。, ただし、今のところ、リッスンするポートを渡すことでServerSocket
を直接作成できます(次のセクションではServerSocketFactory
について詳しく)。
ServerSocket serverSocket = new ServerSocket( port );
そして、accept()
メソッド:
Socket socket = serverSocket.accept();// Handle the connection ...
javaソケットを使用したマルチスレッド-プログラミング
以下のリスト2では、これまでのすべてのサーバー-コードを、スレッドを使用して複数のリクエストを処理する少し堅牢な例にまとめました。, 表示されるサーバーはエコーサーバーであり、受信したメッセージをエコーバックします。
リスト2の例は複雑ではありませんが、NIOの次のセクションで起こることのいくつかを予期しています。 複数の同時リクエストを処理できるサーバーを構築するために記述する必要があるスレッドコードの量に特に注意してください。
リスト2. シンプルソケットサーバー。java
リスト2では、新しいSimpleSocketServer
インスタンスを作成し、サーバーを起動します。, これは、SimpleSocketServer
がThread
を拡張して、ブロッキングを処理する新しいスレッドを作成するために必要ですaccept()
read()
メソッド run()
メソッドは、クライアント要求を受け入れ、要求を処理するためのRequestHandler
スレッドを作成するループ内にあります。 これは比較的簡単なコードでも、フレプログラミング,
RequestHandler
は、リスト1のコードと同じようにクライアント通信を処理します。OutputStream
をPrintStream
でラップして、簡単な書き込みを容易にし、同様にInputStream
を読みやすいように。 サーバーが行く限り、クライアントから行を読み取り、それらをクライアントにエコーバックします。 クライアントが空の行を送信すると、会話は終わり、RequestHandler
はソケットを閉じます。
NIOおよびNIO。,2
多くのアプリケーションでは、先ほど調べたjavaソケットプログラミングの基本モデルで十分です。 より集中的なI/Oまたは非同期入出力を含むアプリケーションでは、Java NIOおよびNIOで導入されたノンブロッキングApiに精通している必要があります。2.
JDK1.4NIOパッケージは、次の主要な機能を提供します。
- チャネルは、あるNIOバッファーから別のNIOバッファーへの一括転送をサポートするように設計されています。
- バッファは、単純な操作のセットによってインターフェイスされる連続したメモリブロックを表します。,
- ノンブロッキング入出力は、ファイルやソケットなどの一般的なI/Oソースにチャネルを公開するクラスのセットです。
NIOでプログラミングするときは、宛先へのチャネルを開き、宛先からデータをバッファに読み込み、データをバッファに書き込み、宛先に送信します。,
- バッファにデータを書き込む
- バッファの
flip()
メソッドを呼び出して読み込む - バッファからデータを読み込む
- バッファの
clear()
またはバッファのclear()
またはcompact()
より多くのデータを受信するためにそれを準備する方法
データがバッファに書き込まれると、バッファはそれに書き込まれたデータの量, 位置:書き込みモードでは、最初の位置は0で、バッファ内に書き込まれている現在の位置を保持します。
Java I/Oデモ:Nioを使用したエコーサーバー。2
NIO.2はJDK7で導入され、JavaのノンブロッキングI/Oライブラリを拡張して、パッケージやjava.nio.file.Path
クラスなどのファイルシステムタスクのサポートを追加し、新しいファイルシステムAPIを公開します。 その背景を念頭に置いて、NIOを使用して新しいEchoサーバーを作成しましょう。2のAsynchronousServerSocketChannel
。
AsynchronousServerSocketChannel
は、ストリーム指向のリッスンソケット用の非ブロッキング非同期チャネルを提供します。, これを使用するには、まず静的なopen()
メソッドを実行し、次にbind()
を特定のポートに実行します。 次に、accept()
メソッドを実行し、CompletionHandler
インターフェイスを実装するクラスを渡します。 ほとんどの場合、そのハンドラーは匿名の内部クラスとして作成されています。
リスト3に、新しい非同期エコー-サーバーのソース-コードを示します。
リスト3. シンプルソケットサーバー。,java
リスト3では、まず新しいAsynchronousServerSocketChannel
を作成し、それをポート5000にバインドします。
final AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));
このAsynchronousServerSocketChannel
から、accept()
を呼び出して、接続のリッスンを開始し、カスタム
インスタンス。 私たちが呼び出すときaccept()
、それはすぐに戻ります。, この例は、リスト1のServerSocket
クラスとは異なりますが、accept()
メソッドはクライアントが接続するまでブロックされますが、AsynchronousServerSocketChannel
accept()
メソッドはこれを処理します。
完了ハンドラ
次の責任は、CompletionHandler
クラスを作成し、completed()
およびfailed()
メソッドの実装を提供することです。, completed()
メソッドは、AsynchronousServerSocketChannel
がクライアントからの接続を受信し、クライアントへのAsynchronousSocketChannel
を含むときに呼び出されます。 completed()
メソッドは、まずAsynchronousServerSocketChannel
からの接続を受け入れ、クライアントとの通信を開始します。 こんにちは、”Hello”メッセージを書き出すことです。文字列を作成し、バイト配列に変換してから、ByteBuffer.wrap()
に渡して、ByteBuffer
。。。。。。。。。。。。。。, その後、ByteBuffer
AsynchronousSocketChannel
のwrite()
メソッドを渡すことができます。
クライアントから読み取るために、新しいByteBuffer
を作成しますallocate(4096)
(4Kバッファを作成します)を呼び出し、次にAsynchronousSocketChannel
のread()
メソッドを呼び出します。 read()
は、Future<Integer>
を返します。get()
を呼び出して、クライアントから読み取ったバイト数を取得します。, この例では、get()
20秒のタイムアウト値を渡します:20秒で応答が得られない場合、get()
メソッドはTimeoutException
をスローします。 このエコーサーバーのルールは、20秒の沈黙を観察すると、会話を終了するということです。
次に、クライアントから受け取った最後のバイトの位置になるバッファの位置を確認します。 クライアントが空の行を送信した場合、キャリッジリターンと改行の二つのバイトを受け取ります。, このチェックは、クライアントが空白行を送信した場合、クライアントが会話を終了したことを示す指標としてそれを取ることを保証します。 意味のあるデータがある場合は、ByteBuffer
のflip()
メソッドを呼び出して読み取りの準備をします。 クライアントから読み取ったバイト数を保持する一時バイト配列を作成し、ByteBuffer
のget()
を呼び出してそのバイト 最後に、新しいString
インスタンスを作成して、バイト配列を文字列に変換します。, 文字列をバイト配列に変換し、それをByteBuffer.wrap()
メソッドに渡し、AsynchronousSocketChannel
のwrite()
メソッドを呼び出します。 ここで、clear()
ByteBuffer
これは、position
をゼロに再配置し、ByteBuffer
を書き込みモードにしてから、クライアントから次の行を読み取ります。,
注意すべきことは、サーバーを作成するmain()
メソッドも、アプリケーションの実行を維持するために60秒のタイマーを設定することだけです。 AsynchronousSocketChannel
のaccept()
メソッドはすぐに返されるため、Thread.sleep()
がない場合、アプリケーションはすぐに停止します。,
これをテストするには、サーバーを起動し、telnetクライアントを使用して接続します。
telnet localhost 5000
いくつかの文字列をサーバーに送信し、それらがエコーバックされていることを確認し、空の行を送信して会話を終了します。
結論として
この記事では、javaを使用したソケットプログラミングに対する二つのアプローチを紹介しました。Java1.0で導入された伝統的なアプローチと、新しいノンブロッキングNIOとNIOで導入されたものです。2つのアプローチは、それぞれJava1.4とJava7で導入されました。, 基本的なJava I/Oの有用性と、ノンブロッキングI/OがJavaソケットプログラミングモデルを改善するいくつかのシナリオの両方を示す、Java socket clientとJava socket server 非ブロッキングI/O、プログラムすることが可能ですJavaネットワークへの応用を扱う複数の同時接続せずに複数のスレッドます。 また、NIOとNIOに組み込まれている新しいサーバーのスケーラビリティを活用することもできます。2.