這是我參與更文挑戰的第14天,活動詳情查看: 更文挑戰java
private static final ThreadLocal<ExecutorService> executorService = new ThreadLocal<ExecutorService>() {
@Override
protected ExecutorService initialValue() {
return Executors.newFixedThreadPool(5);
}
};
複製代碼
public static void start() throws IOException {
try {
// 經過構造函數建立ServerSocket
server = new ServerSocket(HostConstant.PORT);
System.out.println("服務器已啓動,端口號:" + HostConstant.PORT);
while (true) {
// 真正處理的仍是Socket
Socket socket = server.accept();// 阻塞方法
// 把客戶端請求打包成一個任務,放到線程池執行
executorService.get().execute(new ServerHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (server != null) {
server.close();
}
}
}
複製代碼
public class ServerHandler implements Runnable {
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
String message;
String result;
// 經過輸入流讀取客戶端傳輸的數據
while ((message = br.readLine()) != null) {
System.out.println("server receive data:" + message);
result = response(message);
// 將業務結果經過輸出流返回給客戶端
pw.println(result);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
socket = null;
}
}
}
// 返回給客戶端的應答
public static String response(String msg) {
return "Hello," + msg + ",Now is " + new java.util.Date(System.currentTimeMillis()).toString();
}
}
複製代碼
##client編程
public class BIOClient {
public void startConnect() {
try {
Socket socket = new Socket(HostConstant.IP, HostConstant.PORT);
new ReadMsg(socket).start();
PrintWriter pw = null;
// 寫數據到服務端
pw = new PrintWriter(socket.getOutputStream());
pw.println(UUID.randomUUID());
pw.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public static class ReadMsg extends Thread {
Socket socket;
public ReadMsg(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String line = null;
// 經過輸入流讀取服務端傳輸的數據
while ((line = br.readLine()) != null) {
System.out.printf("%s\n", line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Integer time = 6;
for (Integer i = 0; i < time; i++) {
new BIOClient().startConnect();
}
}
}
複製代碼
上面服務端和客戶端其實是僞異步。表面上看起來不會由於客戶端的增長致使內存溢出。可是由於實際上仍是accpet同步阻塞等待。因此在鏈接性能上仍是很差。服務器
咱們在ServerHanndler中是讀取客戶端傳輸的數據經過BufferedReader.readLine這個方法。咱們跟蹤下去發現實際調用的是InputStream.read這個方法。markdown
/** * Reads the next byte of data from the input stream. The value byte is * returned as an <code>int</code> in the range <code>0</code> to * <code>255</code>. If no byte is available because the end of the stream * has been reached, the value <code>-1</code> is returned. This method * blocks until input data is available, the end of the stream is detected, * or an exception is thrown. * * <p> A subclass must provide an implementation of this method. * * @return the next byte of data, or <code>-1</code> if the end of the * stream is reached. * @exception IOException if an I/O error occurs. */
public abstract int read() throws IOException;
複製代碼
NIO=Non Block IO .即非阻塞式編程。網絡
##ByteBuffer框架
##Channeldom
ServerSocketChannel
和SocketChannel
都是Channel的子類。##Selector異步
-多路複用器。這裏咱們能夠理解爲註冊中心。全部的handler再向selector註冊的時候會帶上標籤(SelectorKey)。在某個Channel發生讀或寫的事件時這個Channel會處於就緒狀態。在Selector輪詢的時候會篩選出來。而後咱們在根據SelectorKey判斷監聽的是什麼事件。從而作出處理。查閱資料得知selector沒有鏈接限制。理論上一個selector能夠管理N個Channel。socket
關於NIO2.0 和nettry 他們在次基礎上進行提高!不得不說如今基本上是netty的天下了。下章節咱們針對netty來展開討論!今天端午節不說了我吃糉子去了tcp
記得吃完糉子,回來點個贊哦!!!