Java Socket(套接字)通常也稱作"套接字",用於描述IP地址和端口,是一個通信鏈的句柄。應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求。
使用Socket實現多個客戶端和同一客戶端通訊;首先客戶端連接服務端發送一條消息,服務端接收到消息後進行處理,完成後再回复客戶端一條消息。本人通過自己的思維編寫了一份服務端和客戶端實現的代碼,望能與大家相互學習,共同進步。
服務端代碼
/** * Socket服務端* 功能說明: * */public class Server {/** * 入口* * @param args * @throws IOException */public static void main(String[] args) throws IOException {// 為了簡單起見,所有的異常信息都往外拋int port = 8899;// 定義一個ServiceSocket監聽在端口8899上ServerSocket server = new ServerSocket(port);System.out.println("等待與客戶端建立連接...");while (true) {// server嘗試接收其他Socket的連接請求,server的accept方法是阻塞式的Socket socket = server.accept();/** * 我們的服務端處理客戶端的連接請求是同步進行的, 每次接收到來自客戶端的連接請求後, * 都要先跟當前的客戶端通信完之後才能再處理下一個連接請求。 這在並發比較多的情況下會嚴重影響程序的性能, * 為此,我們可以把它改為如下這種異步處理與客戶端通信的方式*/// 每接收到一個Socket就建立一個新的線程來處理它new Thread(new Task(socket)).start();}// server.close();}/** * 處理Socket請求的線程類*/static class Task implements Runnable {private Socket socket;/** * 構造函數*/public Task(Socket socket) {this.socket = socket;}@Override public void run() {try {handlerSocket();}catch (Exception e) {e.printStackTrace();}}/** * 跟客戶端Socket進行通信* * @throws IOException */private void handlerSocket() throws Exception {// 跟客戶端建立好連接之後,我們就可以獲取socket的InputStream,並從中讀取客戶端發過來的信息了/** * 在從Socket的InputStream中接收數據時,像上面那樣一點點的讀就太複雜了, * 有時候我們就會換成使用BufferedReader來一次讀一行* * BufferedReader的readLine方法是一次讀一行的,這個方法是阻塞的,直到它讀到了一行數據為止程序才會繼續往下執行, * 那麼readLine什麼時候才會讀到一行呢?直到程序遇到了換行符或者是對應流的結束符readLine方法才會認為讀到了一行, * 才會結束其阻塞,讓程序繼續往下執行。 * 所以我們在使用BufferedReader的readLine讀取數據的時候一定要記得在對應的輸出流裡面一定要寫入換行符( * 流結束之後會自動標記為結束,readLine可以識別),寫入換行符之後一定記得如果輸出流不是馬上關閉的情況下記得flush一下, * 這樣數據才會真正的從緩衝區裡面寫入。 */BufferedReader br = new BufferedReader( new InputStreamReader(socket.getInputStream(), "UTF-8"));StringBuilder sb = new StringBuilder();String temp;int index;while ((temp = br.readLine()) != null) {if ((index = temp.indexOf("eof")) != -1) {// 遇到eof時就結束接收sb.append(temp.substring(0, index));break;}sb.append(temp);}System.out.println("Form Cliect[port:" + socket.getPort() + "] 消息內容:" + sb.toString());// 回應一下客戶端Writer writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");writer.write(String.format("Hi,%d.天朗氣清,惠風和暢!", socket.getPort()));writer.flush();writer.close();System.out.println( "To Cliect[port:" + socket.getPort() + "] 回复客戶端的消息發送成功");br.close();socket.close();}}}客戶端代碼
import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.Reader;import java.io.Writer;import java.net.Socket;/** * Socket客戶端* 功能說明: * * @author 大智若愚的小懂* @Date 2016年8月30日* @version 1.0 */public class Client {/** * 入口* @param args */public static void main(String[] args) {// 開啟三個客戶端,一個線程代表一個客戶端for (int i = 0; i < 3; i++) {new Thread(new Runnable() {@Override public void run() {try {TestClient client = TestClientFactory.createClient();client.send(String.format("Hello,Server!I'm %d.這週末天氣如何。", client.client.getLocalPort()));client.receive();}catch (Exception e) {e.printStackTrace();}}}).start();}}/** * 生產測試客戶端的工廠*/static class TestClientFactory {public static TestClient createClient() throws Exception {return new TestClient("127.0.0.1", 8899);}}/** * 測試客戶端*/static class TestClient {/** * 構造函數* @param host 要連接的服務端IP地址* @param port 要連接的服務端對應的監聽端口* @throws Exception */public TestClient(String host, int port) throws Exception {// 與服務端建立連接this.client = new Socket(host, port);System.out.println("Cliect[port:" + client.getLocalPort() + "] 與服務端建立連接...");}private Socket client;private Writer writer;/** * 發送消息* @param msg * @throws Exception */public void send(String msg) throws Exception {// 建立連接後就可以往服務端寫數據了if(writer == null) {writer = new OutputStreamWriter(client.getOutputStream(), "UTF-8");}writer.write(msg);writer.write("eof/n");writer.flush();// 寫完後要記得flush System.out.println("Cliect[port:" + client.getLocalPort() + "] 消息發送成功");}/** * 接收消息* @throws Exception */public void receive() throws Exception {// 寫完以後進行讀操作Reader reader = new InputStreamReader(client.getInputStream(), "UTF-8");// 設置接收數據超時間為10秒client.setSoTimeout(10*1000);char[] chars = new char[64];int len;StringBuilder sb = new StringBuilder();while ((len = reader.read(chars)) != -1) {sb.append(new String(chars, 0, len));}System.out.println("Cliect[port:" + client.getLocalPort() + "] 消息收到了,內容:" + sb.toString());reader.close();// 關閉連接writer.close();client.close();}}}接下來模擬一下:
1.首先運行服務端
2.接著運行客戶端(開三個客戶端請求)
為了演示有所區分,服務端我使用的是Eclipse工具,客戶端使用的是IntelliJ IDEA工具。這時可以看到客戶端在控制台打印出來的消息
一個Port端口號代表一個客戶端,回過來看下服務端在控制台打印出來的消息
總結
以上就是本文關於Java編程Socket實現多個客戶端連接同一個服務端代碼的全部內容,希望對大家有所幫助。有問題可以留言,小編會及時回復大家的。