使用java 和 reids list 实现 socket 长连接 实现发送消息

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用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();
        }
    }


}

以上便是所有了,剩下的就是根据实际项目去修改代码了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值