移动端需要实时的获取服务器的数据
持久化连接就是所谓的长连接,现在基本上不会使用原生的Socket来实现长连接,都是使用第三方的推送服务,如极光推送、小米推送等,这里只是使用Socket来简要说明长连接的原理
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个外观模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
交互如下:
服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束
整个通讯过程,客户端和服务端只用一个Socket对象,长期保持Socket的连接,这种称之为“长连接”;每一次请求都新建一个Socket,处理完成之后直接关闭Socket,这种称之为“短连接”。所以,其实区分长短连接就是:整个客户和服务端的通讯过程是利用一个Socket还是多个Socket进行的
我们在eclipse中新建两个Java工程SocketClient、SocketServer来来模拟客户端和服务器端
客户端:SocketClient
功能:既可以主动的向服务器端发送信息,也可以被动的接收服务器发来的消息
public class SocketClient {
public static void main(String[] args) {
SocketClient client = new SocketClient();
client.start();
}
private void start() {
BufferedReader inputReader = null;
BufferedReader reader = null;
BufferedWriter writer = null;
Socket socket = null;
try {
// 连接目标
socket = new Socket("192.168.1.101", 9898);
// 读取socket的内容
reader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
// 写入socket的内容
writer = new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream()));
// 获取控制台输入
inputReader = new BufferedReader(new InputStreamReader(System.in));
// 对服务器的监听,收到来自服务器的内容
startServerReplyListener(reader);
// 控制台输入
String inputContent;
while (!(inputContent = inputReader.readLine()).equals("bye")) {
//向服务器主动发送消息
writer.write(inputContent+"\n");
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//注意这里的关闭socket是为了客户端出现异常的时候关闭,正常是执行try块的while()循环
reader.close();
writer.close();
inputReader.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void startServerReplyListener(final BufferedReader reader) {
new Thread(new Runnable() {
@Override
public void run() {
try {
String response;
while ((response = reader.readLine()) != null) {
System.out.println(response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
服务器:SocketServer
功能:可主动的接收客户端的信息,主动的推送消息给客户端
package com.zsk.server;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServer {
public static void main(String[] args) {
SocketServer socketServer = new SocketServer();
socketServer.startServer();
}
private void startServer(){
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(9898);
System.out.println("服务已开启...");
while(true){
//当没有Socket连接时,阻塞
socket = serverSocket.accept();
//管理连接
manageConnection(socket);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void manageConnection(final Socket socket){
new Thread(new Runnable() {
@Override
public void run() {
BufferedReader reader = null;
BufferedWriter writer = null;
try {
System.out.println("client:"+socket.hashCode()+"已连接");
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String receivedMsg;
/**
这一段可以模拟服务器端主动推送消息,只不过太过粗糙
new Timer().schedule(new TimerTask() {
@Override
public void run() {
try {
writer.write("server reply: " + "服务器推送!!!" + "\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}, 3000,3000);
*/
//将接收到的数据,重新返回给客户端
while((receivedMsg = reader.readLine()) != null) {
System.out.println("client"+socket.hashCode()+receivedMsg);
writer.write("server reply: " + receivedMsg + "\n");
writer.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
reader.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
在服务器SocketServer中可以看到,每一次的连接都是新开一个线程,这就是很大的一个弊端,当有很多的连接的时候,比方说数十万的连接时,这种高并发的情况对于这种处理方法是不可取的,同时这种方式是阻塞式的,需要开线程去进行维护,考虑到这种情况,Java1.4之后新加了nio可以提供多路非阻塞式的高伸缩性网络,但是这种方式使用十分复杂,所以多是采用基于nio的第三方框架如Mina、Nety
https://www.cnblogs.com/wangcq/p/3520400.html
https://www.jianshu.com/p/b9f3f6a16911