在之前分析zookeeper源码的过程当中,有两个地方使用到了基于java socket进行通信的地方
第一个地方是在集群启动时,集群节点之间会发起leader投票选举,此时zookeeper底层是基于java socket来进行网络通信的,感兴趣的小伙伴可以看 手把手带你撸zookeeper源码-zookeeper启动(三)(zookeeper选举时是如何基于socket建立连接的) 这篇文章
第二个地方是当集群中新加入一个zk节点或者某个节点宕机恢复启动的时候,需要恢复数据,并且从leader中同步数据,此时也是基于java socket进行网络通信的 手把手带你撸zookeeper源码-zookeeper确定好角色后会做什么?
这篇文章简单来个基于java socket来进行网络通信的小demo,然后把java socket网络通信和zookeeper中的网络结合起来,可以有更深入的理解
server端代码
public class SocketServer {
private static final int _1M = 1024 * 1024;
public static void main(String[] args) throws Exception {
//监听server端口号9000
ServerSocket serverSocket = new ServerSocket(9000);
while(true) {
//创建一个socket和客户端通信
Socket socket = serverSocket.accept();//阻塞住, 等待客户端发来链接、请求
//创建一个线程,来处理客户端发来的请求
// 每个客户端和服务端建立链接都会创建一个线程,当有100W个客户端来建立链接,服务端就会创建100W个线程会处理
new Worker(socket).start();
}
}
static class Worker extends Thread {
Socket socket;
public Worker(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//初始化1M的内存缓存
char[] buf = new char[_1M];
InputStreamReader reader = new InputStreamReader(socket.getInputStream());
OutputStream out = socket.getOutputStream();
//读取客户端发过来的数据
int len = reader.read(buf);//会进行阻塞,等待客户端发送过来的数据
while(len != -1) {
String data = new String(buf, 0, len);
System.out.println(Thread.currentThread().getName() + "服务端接受了请求: " + data);
//服务端返回响应数据
out.write("收到, 收到".getBytes());
//继续读取
len = reader.read(buf);
}
out.close();
reader.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
client端代码
public class SocketClient {
private static final int _1M = 1024 * 1024;
public static void main(String[] args) throws Exception {
//和server端建立链接请求, server端会创建一个和客户端绑定通信的socket
Socket socket = new Socket("localhost", 9000);
OutputStream out = socket.getOutputStream();
//创建1M的字符缓冲区
char[] buf = new char[_1M];
InputStreamReader reader = new InputStreamReader(socket.getInputStream());
while(true) {
try {
// 往服务端发送数据
out.write("你好".getBytes());
//把读取到的数据放入到字符缓冲区
int len = reader.read(buf); //会进行阻塞等待读取服务端发送回来的数据
if(len != -1) {
String data = new String(buf, 0 , len);
System.out.println("客户端接收到了响应: " + data);
}
Thread.sleep(1000);
} catch (Exception e) {
reader.close();
out.close();
socket.close();
}
}
}
}
最后的运行结果就不粘贴出来了,客户端一直往服务端发送数据,服务端接收到数据之后会响应数据给客户端
基于java socket的网络编程是基于阻塞式的,服务端会阻塞等待客户端发送链接,然后还会阻塞等待客户端发送过来数据。
客户端会阻塞等待服务端响应数据,一直都是阻塞的状态。