Socket 相關資料(隨筆)
阿新 • • 發佈:2018-03-02
gpo har 數據類型 ext 由於 throw ack 應該 soc
由於項目上的 http 請求量較大,項目上性能跟不上。於是考慮把 短連接的 http 換成 長連接的tcp 形式 試試效果。
先 研究了一下 長連接方式。就是要用到 socket 方面的知識。
package com.bkc.bpmp.common.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket;/** * 搭建服務器端 a)、創建ServerSocket對象綁定監聽端口。 b)、通過accept()方法監聽客戶端的請求。 c)、建立連接後,通過輸入輸出流讀取客戶端發送的請求信息。 d)、通過輸出流向客戶端發送請求信息。 e)、關閉相關資源。 * @author ppnie * */ public class SocketService { // 搭建服務器端 public static void main(String[] args) throws IOException { SocketService socketService= new SocketService(); // 1、a)創建一個服務器端Socket,即SocketService socketService.oneServer(); } public void oneServer() { try { ServerSocket server = null; try { server = new ServerSocket(5209);// b)指定綁定的端口,並監聽此端口。 System.out.println("服務器啟動成功"); // 創建一個ServerSocket在端口5209監聽客戶請求 } catch (Exception e) { System.out.println("沒有啟動監聽:" + e); // 出錯,打印出錯信息 } Socket socket = null; try { socket = server.accept(); // 2、調用accept()方法開始監聽,等待客戶端的連接 // 使用accept()阻塞等待客戶請求,有客戶 // 請求到來則產生一個Socket對象,並繼續執行 } catch (Exception e) { System.out.println("Error." + e); // 出錯,打印出錯信息 } // 3、獲取輸入流,並讀取客戶端信息 String line; BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 由Socket對象得到輸入流,並構造相應的BufferedReader對象 PrintWriter writer = new PrintWriter(socket.getOutputStream()); // 由Socket對象得到輸出流,並構造PrintWriter對象 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 由系統標準輸入設備構造BufferedReader對象 System.out.println("Client:" + in.readLine()); // 在標準輸出上打印從客戶端讀入的字符串 line = br.readLine(); // 從標準輸入讀入一字符串 // 4、獲取輸出流,響應客戶端的請求 while (!line.equals("end")) { // 如果該字符串為 "bye",則停止循環 writer.println(line); // 向客戶端輸出該字符串 writer.flush(); // 刷新輸出流,使Client馬上收到該字符串 System.out.println("Server:" + line); // 在系統標準輸出上打印讀入的字符串 System.out.println("Client:" + in.readLine()); // 從Client讀入一字符串,並打印到標準輸出上 line = br.readLine(); // 從系統標準輸入讀入一字符串 } // 繼續循環 // 5、關閉資源 writer.close(); // 關閉Socket輸出流 in.close(); // 關閉Socket輸入流 socket.close(); // 關閉Socket server.close(); // 關閉ServerSocket } catch (Exception e) {// 出錯,打印出錯信息 System.out.println("Error." + e); } } } package com.bkc.bpmp.common.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class SocketClient { // 搭建客戶端 public static void main(String[] args) throws IOException { try { // 1、創建客戶端Socket,指定服務器地址和端口 // Socket socket=new Socket("127.0.0.1",5200); Socket socket = new Socket("192.168.1.99", 5209); System.out.println("客戶端啟動成功"); // 2、獲取輸出流,向服務器端發送信息 // 向本機的52000端口發出客戶請求 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 由系統標準輸入設備構造BufferedReader對象 PrintWriter write = new PrintWriter(socket.getOutputStream()); // 由Socket對象得到輸出流,並構造PrintWriter對象 // 3、獲取輸入流,並讀取服務器端的響應信息 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 由Socket對象得到輸入流,並構造相應的BufferedReader對象 String readline; readline = br.readLine(); // 從系統標準輸入讀入一字符串 while (!readline.equals("end")) { // 若從標準輸入讀入的字符串為 "end"則停止循環 write.println(readline); // 將從系統標準輸入讀入的字符串輸出到Server write.flush(); // 刷新輸出流,使Server馬上收到該字符串 System.out.println("Client:" + readline); // 在系統標準輸出上打印讀入的字符串 System.out.println("Server:" + in.readLine()); // 從Server讀入一字符串,並打印到標準輸出上 readline = br.readLine(); // 從系統標準輸入讀入一字符串 } // 繼續循環 // 4、關閉資源 write.close(); // 關閉Socket輸出流 in.close(); // 關閉Socket輸入流 socket.close(); // 關閉Socket } catch (Exception e) { System.out.println("can not listen to:" + e);// 出錯,打印出錯信息 } } }
這是一個簡單的 用java 實現 socket 客戶端與服務端的 代碼。
但是這樣的例子,並不能實際運用與項目之中。在實際項目中需要考慮到 套接字的連接什麽時候關閉,流什麽時候關閉,參數的傳入與信息的響應都需要得到結果。
若是這裏使用的方法同 http 的話,應該是 一個請求一個對應的響應結果,若是長連接,應該如何把多線程與長連接 結合起來呢?
現在的項目是 使用C++ 服務端 和 java 客戶端 來使用 socket 進行通信。
C++ 與 Java 之間的通信還涉及到了一個 網絡字節碼 不一致的問題。以及 還有一個 自定義協議 的問題
假設 自定義協議 為
java 客戶端代碼(至於這裏的BytePtr ,就是 網絡字節碼 的轉碼)
public class BytePtr { public static byte[] toLH(short n) { byte[] b = new byte[2]; b[0] = (byte) (n & 0xff); b[1] = (byte) (n >> 8 & 0xff); return b; } public static byte [] toLH( int n) { byte [] b = new byte [ 4 ]; b[0 ] = ( byte ) (n & 0xff ); b[1 ] = ( byte ) (n >> 8 & 0xff ); b[2 ] = ( byte ) (n >> 16 & 0xff ); b[3 ] = ( byte ) (n >> 24 & 0xff ); return b; } public static byte[] addBytes(byte[] data1, byte[] data2) { byte[] data3 = new byte[data1.length + data2.length]; System.arraycopy(data1, 0, data3, 0, data1.length); System.arraycopy(data2, 0, data3, data1.length, data2.length); return data3; } } import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; public class ChatClient { public static void main(String[] args) { try { Socket client = new Socket("192.168.1.108", 10008); OutputStream out = client.getOutputStream(); DataOutputStream outs = new DataOutputStream(out); Scanner scaner = new Scanner(System.in); genProtocol(outs, scaner.next()); parseProtocol(client); outs.close(); out.close(); client.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 構造協議 * * @param out * @param msg * @throws IOException */ private static void genProtocol(DataOutputStream out, String msg) throws IOException { short type = 10001; // 消息類型 byte[] bytes = msg.getBytes(); // 消息內容 int totalLen = bytes.length; // 消息長度 out.write((BytePtr.addBytes(BytePtr.addBytes(BytePtr.toLH(type), BytePtr.toLH(totalLen)), bytes))); // 寫入消息內容 out.flush(); } private static void parseProtocol(Socket client) throws IOException { InputStream is = client.getInputStream(); DataInputStream dis = new DataInputStream(is); // 讀取Java標準數據類型的輸入流 // 協議解析 int totalLen = dis.readInt(); // 讀取消息長度 byte[] data = new byte[totalLen]; // 定義存放消息內容的字節數組 int len = is.read(data); String text = new String(data, 0, len); System.out.println("發來的內容是:" + text); is.close(); dis.close(); } }
哦,這裏還提到 一個工具 Wireshark,用來抓取包,來查看一下網絡字節碼到底傳送的是一些什麽
哦,還有 提到的 netty 技術,至於怎麽用,還是先看看再說。
至於 有一些電子書之類的,可以 到腳本之家 去下載。
最最重要的一點,下載的電子書、視頻、源碼 之類的,一定要看啊。
Socket 相關資料(隨筆)