这是我参与更文挑战的第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
记得吃完粽子,回来点个赞哦!!!