この記事では、java に関する関連知識を提供します。主にソケット プログラミングに関する関連コンテンツを紹介します。ソケットとは、ネットワーク ドライバー層によってアプリケーションに提供されるインターフェイスです。見てみましょう。以下の仕組みが皆様のお役に立てば幸いです。
#推奨学習: 「java ビデオ チュートリアル 」
1. ソケットの知識(1) java.net パッケージの 2 つのクラス Socket と ServerSocket は、双方向の安全な接続のクライアント側とサーバー側をそれぞれ実装するために使用されます。 TCP プロトコルについて 作業中の作業プロセスは電話をかけるのと同じで、双方が接続されて初めて通話を開始できます。 (2) ネットワーク通信中、Socket はデータ フローを使用してデータ転送を完了する必要があります。 (3) アプリケーションがネットワーク経由で別のアプリケーションにデータを送信したい場合は、単純にソケットを作成し、そのソケットに関連付けられた出力ストリームにデータを書き込みます。これに応じて、受信アプリケーションはソケットを作成し、関連する入力ストリームからデータを読み取ります。 (4) 注: TCP プロトコルに基づくソケット プログラミングでは、多くの場合、2 つのエンドポイントがクライアントとして機能し、もう 1 つがサーバーとして機能します。つまり、クライアント/サーバー モデルに従います。
● ソケット クラス
Socket オブジェクトは、クライアントとサーバー間の接続を確立します。 Socket クラスのコンストラクター メソッドを使用してソケットを作成し、このソケットを指定したホストとポートに接続できます。 (1) 構築方法 —>最初の構築方法は、ホスト名とポート番号をパラメータとして受け取り、Socket オブジェクトを作成します。オブジェクトの作成時に UnknownHostException または IOException がスローされる場合があるため、これらをキャッチする必要があります。ソケット s = 新しいソケット(ホスト名,ポート);
--> 2 番目の構築メソッドは、InetAddress オブジェクトとポート番号をパラメータとして受け取り、Socket オブジェクトを作成します。コンストラクターは IOException または UnknownHostException をスローする可能性があるため、これらを捕捉して処理する必要があります。
Socket s = new Socket(address,port);
(2) 共通メソッド
● ServerSocket クラス
ServerSocket オブジェクトは、クライアントが接続を確立するのを待機し、接続が確立された後に通信します。
(1)構築メソッド
-->最初の構築メソッドは、ServerSocket オブジェクトを作成するためのパラメータとしてポート番号を受け入れます。このオブジェクトの作成時に、IOException がスローされる場合があります。キャプチャして処理する必要があります。
Serversocket SS = New Serversocket (Port);
##-& GT; 2 番目のコンストラクターは、長さとキューの最大長をパラメーターとして受け取ります。接続が拒否される前に取得できます。 using ss using using ss through ss through to ss = new ss = new ServerSocket(port, maxqu);メソッドは ServerSocket クラスにも適用されます。
—>ServerSocket クラスには accept() メソッドがあり、これはクライアントが通信を開始するのを待機して、Socket オブジェクトをさらなるデータ送信に使用できるようにするために使用されます。
# 2. ソケット プログラミングを使用してログイン機能を実装します(1) 接続を確立します。
(2) ソケットに関連付けられた入出力ストリームを開きます。 (3) データ ストリームに情報を書き込み、データ ストリームから情報を読み取ります。 (4) すべてのデータ ストリームとソケットを閉じます。 -& GT; 2 つのクラスを使用してユーザー ログインの機能をシミュレートし、クライアントがサーバー側にユーザー ログイン情報を送信したことを実現し、その情報をサーバー側で表示します。 クライアント実装手順:1) 接続を確立します。接続はサーバーとポートを指します。
2) ソケットに関連付けられた入出力ストリームを開きます。
3) 情報を出力ストリームに書き込みます。
4) 入力ストリームから応答情報を読み取ります。
5) すべてのデータ ストリームとソケットを閉じます。
サーバー側の実装手順:1) 接続を確立し、ポートをリッスンします。
2) accept() メソッドを使用して、クライアントが通信を開始するのを待ちます。
3) に関連付けられた入出力ストリームを開きます。ソケット。
4) 入力ストリームからリクエスト情報を読み取ります。
5) 情報を出力ストリームに書き込みます。
6) すべてのデータ ストリームとソケットを閉じます。
#-& gt; クライアントとサーバーの対話では、応答モードを採用し、まずサーバーを起動して監視状態に入り、クライアントの接続要求を待ちます。接続が成功すると、クライアントが最初に話します。」、サーバーは「応答」を返します。例 01: オブジェクト情報の転送を実装します。
♥ ユーザー クラス
package cn.bdqn.demo02; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; /** 用户名 */ private String loginName; /** 用户密码 */ private String pwd; public User() { super(); } public User(String loginName, String pwd) { super(); this.loginName = loginName; this.pwd = pwd; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }ログイン後にコピー♥ LoginServer クラス
package cn.bdqn.demo02; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class LoginServer { public static void main(String[] args) { ServerSocket serverSocket = null; Socket socket = null; InputStream is = null; ObjectInputStream ois = null; OutputStream os = null; try { // 建立一个服务器Socket(ServerSocket),指定端口8800并开始监听 serverSocket = new ServerSocket(8800); // 使用accept()方法等待客户端发起通信 socket = serverSocket.accept(); // 打开输入流 is = socket.getInputStream(); // 反序列化 ois = new ObjectInputStream(is); // 获取客户端信息,即从输入流读取信息 User user = (User) ois.readObject(); if (user != null) { System.out.println("我是服务器,客户登录信息为:" + user.getLoginName() + "," + user.getPwd()); } // 给客户端一个响应,即向输出流中写入信息 String reply = "欢迎你,登录成功"; os = socket.getOutputStream(); os.write(reply.getBytes()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { // 关闭资源 try { os.close(); ois.close(); is.close(); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }ログイン後にコピーLoginClient クラス
package cn.bdqn.demo02; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class LoginClient { /* * 示例02:升级演示示例01,实现传递对象信息。 */ public static void main(String[] args) { Socket socket = null; OutputStream os = null; ObjectOutputStream oos = null; InputStream is = null; BufferedReader br = null; try { // 建立客户端Socket连接,指定服务器的位置为本机以及端口为8800 socket = new Socket("localhost", 8800); // 打开输出流 os = socket.getOutputStream(); // 对象序列化 oos = new ObjectOutputStream(os); // 发送客户端信息,即向输出流中写入信息 User user = new User("Tom", "123456"); oos.writeObject(user); socket.shutdownOutput(); // 接收服务器端的响应,即从输入流中读取信息 is = socket.getInputStream(); br = new BufferedReader(new InputStreamReader(is)); String reply; while ((reply = br.readLine()) != null) { System.out.println("我是客户端,服务器的响应为:" + reply); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { br.close(); is.close(); oos.close(); os.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }ログイン後にコピー
例 02:デモ例01をバージョンアップし、複数のオブジェクト情報の送信を実現しました。
ユーザー クラス
package cn.bdqn.demo03; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; /** 用户名 */ private String loginName; /** 用户密码 */ private String pwd; public User() { super(); } public User(String loginName, String pwd) { super(); this.loginName = loginName; this.pwd = pwd; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }ログイン後にコピーLoginServer クラス
package cn.bdqn.demo03; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class LoginServer { public static void main(String[] args) { ServerSocket serverSocket = null; Socket socket = null; InputStream is = null; ObjectInputStream ois = null; OutputStream os = null; try { // 建立一个服务器Socket(ServerSocket),指定端口8800并开始监听 serverSocket = new ServerSocket(8800); // 使用accept()方法等待客户端发起通信 socket = serverSocket.accept(); // 打开输入流 is = socket.getInputStream(); // 反序列化 ois = new ObjectInputStream(is); // 获取客户端信息,即从输入流读取信息 User[] users = (User[]) ois.readObject(); for (int i = 0; i < users.length; i++) { System.out.println("我是服务器,客户登录信息为:" + users[i].getLoginName() + "," + users[i].getPwd()); } // 给客户端一个响应,即向输出流中写入信息 String reply = "欢迎你,登录成功"; os = socket.getOutputStream(); os.write(reply.getBytes()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { // 关闭资源 try { os.close(); ois.close(); is.close(); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }ログイン後にコピーLoginClient クラス
package cn.bdqn.demo03; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class LoginClient { /* * 示例02:升级演示示例01,实现传递对象信息。 */ public static void main(String[] args) { Socket socket = null; OutputStream os = null; ObjectOutputStream oos = null; InputStream is = null; BufferedReader br = null; try { // 建立客户端Socket连接,指定服务器的位置为本机以及端口为8800 socket = new Socket("localhost", 8800); // 打开输出流 os = socket.getOutputStream(); // 对象序列化 oos = new ObjectOutputStream(os); // 发送客户端信息,即向输出流中写入信息 User user1 = new User("Tom", "123456"); User user2 = new User("bob", "123456"); User user3 = new User("lisa", "123456"); User[] users = {user1,user2,user3}; oos.writeObject(users); socket.shutdownOutput(); // 接收服务器端的响应,即从输入流中读取信息 is = socket.getInputStream(); br = new BufferedReader(new InputStreamReader(is)); String reply; while ((reply = br.readLine()) != null) { System.out.println("我是客户端,服务器的响应为:" + reply); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { br.close(); is.close(); oos.close(); os.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }ログイン後にコピー
● 複数のクライアント ユーザーを実装するlogin
## -->一問一答モデルは、明らかに人々が現実に望んでいることではありません。サーバーは 1 つのクライアントにのみサービスを提供することはできませんが、通常は同時に多くのクライアントにサービスを提供しますが、結果的にはシングルスレッド実装でなければなりません。 —>この問題の解決策は、マルチスレッドを使用することです。監視を特に担当するアプリケーション メイン サービス プログラムをサーバー側に作成し、応答を特に担当するスレッド プログラムを作成できます。これにより、マルチスレッドで複数のリクエストを処理できるようになります。 クライアント側の実装手順:1) 接続を確立し、その接続はサーバーとポートを指します。
2) ソケットに関連付けられた入出力ストリームを開きます。
3) 情報を出力ストリームに書き込みます。
4) 入力ストリームから応答情報を読み取ります。
5) すべてのデータ ストリームとソケットを閉じます。
#-& GT; サーバー側の実装手順:1) サーバースレッドクラスを作成し、RUN()メソッドでリクエストの応答処理を行います。
2) サーバー側のソケットが常に待機状態になるようにサーバー側のコードを変更します。
3) サーバーはリクエストを監視するたびに、スレッド オブジェクトを作成して開始します。
例 03: デモ例 02 をアップグレードして、複数のクライアントの応答処理を実装します。
ユーザー クラス-->java.net パッケージの InetAddress クラスは、IP アドレスと DNS をカプセル化するために使用されます。 。このクラスにはコンストラクターがないため、InetAddress クラスのインスタンスを作成するには、ファクトリ メソッドを使用できます。 -& GT; INetaddress クラスのファクトリ メソッド -& GT; ホストが見つからない場合、どちらのメソッドも不明なホスト名例外の異常によりスローされます。 3. UDP プロトコルに基づくソケット プログラミングLoginThreadpackage cn.bdqn.demo04; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; /** 用户名 */ private String loginName; /** 用户密码 */ private String pwd; public User() { super(); } public User(String loginName, String pwd) { super(); this.loginName = loginName; this.pwd = pwd; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }ログイン後にコピーLoginServer クラスpackage cn.bdqn.demo04; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.net.Socket; public class LoginThread extends Thread { /* * 示例03:升级示例02,实现多客户端的响应处理。 * * 分析如下: * (1)创建服务器端线程类,run()方法中实现对一个请求的响应处理。 * (2)修改服务器端代码,让服务器端Socket一直处于监听状态。 * (3)服务器端每监听到一个请求,创建一个线程对象并启动 */ Socket socket = null; //每启动一个线程,连接对应的Socket public LoginThread(Socket socket) { this.socket = socket; } //启动线程,即响应客户请求 public void run() { InputStream is = null; ObjectInputStream ois = null; OutputStream os = null; try { //打开输入流 is = socket.getInputStream(); //反序列化 ois = new ObjectInputStream(is); //获取客户端信息,即从输入流读取信息 User user = (User)ois.readObject(); if(user!=null){ System.out.println("我是服务器,客户登录信息为:"+user.getLoginName()+","+user.getPwd()); } //给客户端一个响应,即向输出流中写入信息 os = socket.getOutputStream(); String reply = "欢迎你,登录成功"; os.write(reply.getBytes()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }finally{ try { os.close(); ois.close(); is.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }ログイン後にコピー♥ LoginClient1 クラスpackage cn.bdqn.demo04; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class LoginServer { public static void main(String[] args) { ServerSocket serverSocket = null; try { // 建立一个服务器Socket(ServerSocket)指定端口并开始监听 serverSocket = new ServerSocket(8800); // 监听一直进行中 while (true) { // 使用accept()方法等待客户发起通信 Socket socket = serverSocket.accept(); LoginThread loginThread = new LoginThread(socket); loginThread.start(); } } catch (IOException e) { e.printStackTrace(); } } }ログイン後にコピー♥ LoginClient2クラスと LoginClient3 クラス LoginClient1 クラスと同様に、別の User オブジェクトを作成するだけですpackage cn.bdqn.demo04; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class LoginClient01 { /* * 客户端通过输出流向服务器端发送请求信息 * 服务器侦听客户端的请求得到一个Socket对象,将这个Socket对象传递给线程类 * 线程类通过输入流获取客户端的请求并通过输出流向客户端发送响应信息 * 客户端通过输入流读取服务器发送的响应信息 * */ /* * 示例03:升级演示示例02,实现多客户端的响应处理 */ public static void main(String[] args) { Socket socket = null; OutputStream os = null; ObjectOutputStream oos = null; InputStream is = null; BufferedReader br = null; try { // 建立客户端Socket连接,指定服务器的位置为本机以及端口为8800 socket = new Socket("localhost", 8800); // 打开输出流 os = socket.getOutputStream(); // 对象序列化 oos = new ObjectOutputStream(os); // 发送客户端信息,即向输出流中写入信息 User user = new User("Tom", "123456"); oos.writeObject(user); socket.shutdownOutput(); // 接收服务器端的响应,即从输入流中读取信息 is = socket.getInputStream(); br = new BufferedReader(new InputStreamReader(is)); String reply; while ((reply = br.readLine()) != null) { System.out.println("我是客户端,服务器的响应为:" + reply); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { br.close(); is.close(); oos.close(); os.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }ログイン後にコピー
##TCP |
UDP | |
接続指向 | 非接続指向 | |
信頼できる | 信頼できない | |
##遅い | 速い |
以上がJAVA 高度な学習ソケット プログラミングの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。