编程中的Socket是什么?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,其实就是一个门面模式。
BIO的阻塞提现在两个方面
若一个服务器启动就绪,那么服务器的主线程就一直等待着客户端连接,这个等待过程中主线程就在阻塞。
public class ServerSingle {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8888));
System.out.println(“Start Server …”);
int connectCount = 0;
try {
while (true){
Socket socket = serverSocket.accept();
System.out.println("accept client socket ....total =" + ( ++connectCount));
ObjectInputStream inputStream =
new ObjectInputStream(socket.getInputStream());
ObjectOutputStream outputStream =
new ObjectOutputStream(socket.getOutputStream());
String userName = inputStream.readUTF();
System.out.println("Accept client message:"+userName);
outputStream.writeUTF("Hello,"+userName);
outputStream.flush();
}
}catch (Exception e){
e.printStackTrace();
}finally {
serverSocket.close();
}
}
}
可以看到主线程启动,线程阻塞在了accept()监听方法,后面的没有打印
在连接建立之后,在读到socket信息之前,线程也是一直在等待的,阻塞在那里。
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = null;
ObjectOutputStream output = null;
ObjectInputStream input = null;
InetSocketAddress addr
= new InetSocketAddress(“127.0.0.1”,8888);
try {
socket = new Socket();
socket.connect(addr);
System.out.println("Connect Server success!!");
output = new ObjectOutputStream(socket.getOutputStream());
input = new ObjectInputStream(socket.getInputStream());
System.out.println("Ready send message.....");
output.writeUTF("yang");
output.flush();
System.out.println(input.readUTF());
} catch (IOException e) {
e.printStackTrace();
}finally {
if (socket!=null) socket.close();
if (output!=null) output.close();
if (input!=null) input.close();
}
}
}
我们在client中打上断点,debug启动。可以看到client连接成功,server端的accept也接收到了,但是主线程又阻塞在了等待socket的输出当中
NIO和BIO的主要区别
NIO三大核心组件
重要概念:SelectionKey
SelectionKey是一个抽象类,表示selectableChannel在Selector中注册的标识,其中有四种状态分别是OP_READ(读事件),OP_WRITE(写事件),OP_CONNECT(发起连接事件),OP_ACCEPT(接收连接事件)
直接内存比堆内存快在哪
jvm在向socket缓冲区发送信息时,会在堆外重新开辟一块内存,将要发送的信息拷贝进去。这样做的原因是防止在gc的时候,改变堆内信息的位置。
堆外内存的优点和缺点
堆外内存相比于堆内内存有几个优势:
1 减少了垃圾回收的工作,因为垃圾回收会暂停其他的工作(可能使用多线程或者时间片的方式,根本感觉不到)
2 加快了复制的速度。因为堆内在flush到远程时,会先复制到直接内存(非堆内存),然后在发送;而堆外内存相当于省略掉了这个工作。
而福之祸所依,自然也有不好的一面:
1 堆外内存难以控制,如果内存泄漏,那么很难排查
2 堆外内存相对来说,不适合存储很复杂的对象。一般简单的对象或者扁平化的比较适合。