使用springboot 和 redis 的list 的队列属性 实现 socket 长连接请求服务器功能
话不多说直接上代码:
package com.veoer.mind.manager;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
/**
* auth wxt 2020-01-15
* socket 长连接处理
*/
@Component
@Configuration
public class SocketClientLonManager {
private Socket mSocket = null;
private OutputStream outputStream;//输出流,用于发送心跳
@Value("${socket_client.host}")
private String host;//="192.168.254.36";
@Value("${socket_client.port}")
private int port;//=9877;
@Autowired
private RedisManager redisManager;
public SocketClientLonManager() {
}
/**
* 这里来个初始化
*/
public void init(){
// 创建 socket 并连接服务器
try {
mSocket = new Socket(host, port);
if(!mSocket.getKeepAlive()) mSocket.setKeepAlive(true);//true,若长时间没有连接则断开
if(!mSocket.getOOBInline())mSocket.setOOBInline(true);//true,允许发送紧急数据,不做处理
outputStream = mSocket.getOutputStream();//获得socket的输出流
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
// 和服务端进行通信
Thread readerThread = new Thread(this::readResponse);
readerThread.start();
//来一个心跳包
Thread heardThread = new Thread(this::startThreadSocket);
heardThread.start();
try {
if (mSocket.isClosed()){
SocketAddress socketAddress = new InetSocketAddress(host,port);
mSocket.connect(socketAddress);
}
//向服务器端第一次发送字符串
DataOutputStream doc = new DataOutputStream(outputStream);
while (true) {
String msg = redisManager.rightPop("device_send_msg",100, TimeUnit.HOURS);
doc.writeUTF(msg);
outputStream.flush();
}
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 返回的结果
*/
private void readResponse() {
try {
DataInputStream in = new DataInputStream(mSocket.getInputStream());
//向服务器端第二次发送字符串
while (true) {
String res = in.readUTF();
if (!"".equals(res) && null != res ) {
JSONObject revertjson = JSONObject.fromObject(res);
if("heartbeat".equals(revertjson.getString("type"))){
redisManager.leftPush("device_revert_heartbeat", res);
redisManager.setExpire("device_revert_heartbeat",18L, TimeUnit.SECONDS);
}else{
redisManager.leftPush("device_revert_msg", res);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 心跳包发送
*/
public void startThreadSocket(){
final String socketContent = "{\"type\":\"heartbeat\"}";// + "\n";
while (true) {
try {
Thread.sleep(20 * 1000);//20s发送一次心跳
redisManager.leftPush("device_send_msg",socketContent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
最基础的socket 类
项目启动时启动socket 发送心跳包
package com.veoer.mind.config;
import com.veoer.mind.manager.SocketClientLonManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(value = 2)
public class SocketStartInint implements ApplicationRunner {
@Autowired
SocketClientLonManager socketClientLonManager;
@Override
public void run(ApplicationArguments args) throws Exception {
//启动socket 长连接 线程。
System.out.println("socket Init");
socketClientLonManager.init();
socketClientLonManager.run();
}
}
//服务端
package com.wxt.socket.demo.socketclient;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
private final ServerSocket mServerSocket;
public EchoServer(int port) throws IOException {
// 1. 创建一个 ServerSocket 并监听端口 port
mServerSocket = new ServerSocket(port);
}
public void run() throws IOException {
// 2. 开始接受客户连接
Socket client = mServerSocket.accept();
handleClient(client);
}
private void handleClient(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
byte[] buffer = new byte[1024];
int n;
while ((n = in.read(buffer)) > 0) {
System.out.write(buffer, 0, n);
out.write(buffer, 0, n);
}
}
public static void main(String[] argv) {
try {
EchoServer server = new EchoServer(9877);
server.run();
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上便是所有了,剩下的就是根据实际项目去修改代码了。

本文介绍如何使用SpringBoot结合Redis的List特性,实现socket的长连接功能,通过发送心跳包保持连接活跃,并展示如何在项目启动时初始化socket连接。
4020

被折叠的 条评论
为什么被折叠?



