socket通信是基于底层TCP/IP协议实现的。这种服务端不需要任何的配置文件和tomcat就可以完成服务端的发布,使用纯java代码实现通信。socket是对TCP/IP的封装调用,本身并不是一种协议,我们通过socket来调用协议来跟服务端进行通信和数据的传输。socket就像客户端与服务端之间的一条信息通道,每一个不同的客户端都会建立一个独立的socket,双方都没有关闭连接的话,连接—也就是建立好的这条socket通道将一直保持,服务端要跟那一个客户端通信只需要找到对应的socket对象就可以进行数据传递。
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
一. 服务端:在客户端跟服务端通信之前,服务端必须先开启。首先来看一下服务端Socket的编写吧。服务端就是一个简单的java项目,由于聊天室可能会有多个客户端同时连接并发送消息,我们这里使用线程池来处理客户端的请求。
List<Socket> list = new ArrayList<Socket>();
ExecutorService executorService;
BufferedReader br;
private static final int PORT = 12345;
private static final int POOL_SIZE = 5 ;
public Socket_Server() throws IOException {
executorService = Executors.newFixedThreadPool(POOL_SIZE);
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println(serverSocket.getInetAddress().getHostAddress() + ":服务端就绪。");
Socket client = null;
while (true) {
//为每一个连接到服务器的客户端分配一个线程进行消息的接收和发送
client = serverSocket.accept();
list.add(client);
executorService.execute(new Service(client));
}
}
首先我们创建了一个大小为5的固定大小线程池,并创建端口号为12345的服务端socket接收客户端请求,通过一个while循环不断轮询来自服务端的连接请求,在while循环里面调用了serverSocket.accept();是线程进入阻塞状态,也就是说在没有接收到客户端的请求时,程序将一直停留在这里,当有客户端连接服务端是,代码开始往下走,我们把接收到的客户端socket放入list里面,这样我们就把所有连接到服务端的socket保存下来了,这样就使得我们可以随时对任一客户端进行数据传递。之后就是线程池调用execute执行一个线程,把连接过来的socket作为参数传进去。接下来分析下service的内容:
class Service implements Runnable {
Socket client;
BufferedReader br;
String msg = "";