springboot通过socket接收数据用websocket推送给前端,人机交互界面展示

目前要做人机交互界面的后台,人机对话内容需要实时展示在机器人屏幕上,人机对话的内容由语音系统推送到后台,用的是tcp协议,tcp的服务端我不用管,现在我需要把语音系统推给我的内容给到前端;由于语音系统底层才用的是C和C++;不方便用websocket,不然前端可以直接用websocket接收语音系统的数据。
实现想法:后台用socket来接收语音系统的数据,再搭建一个websocket服务端把接受到的数据推送给前端

socket客户端:ClientTestCommunicate

@Component
public class ClientTestCommunicate extends Thread  {



    // public static void main(String[] args) {
    public static void start(String[] args) {
        try {
            //Socket client = new Socket("192.168.5.8", 17080);
            Socket client = new Socket("127.0.0.1", 1234);
            // client.setSoTimeout(20000);//设置socket连接时间

            System.out.println("当前是客户端窗口:");
            new CReceiveMsgThread(client).start();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public void start() {
        start(null);
    }

}

// 接收消息线程

class CReceiveMsgThread extends Thread {


    //  这里使用静态,让 service 属于类
    /*private static WebSocketProcess webSocketProcess;

    @Autowired
    public void setWebSocketProcess(WebSocketProcess webSocketProcess) {
        CReceiveMsgThread.webSocketProcess = webSocketProcess;
    }
*/
    Socket client;

    public CReceiveMsgThread(Socket client) {
        this.client = client;
    }

    @Override
    public void run() {
      //  new SendMsgThread(client).start();
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
            String str;
            while (!client.isClosed()&&(str = reader.readLine()) != null) {
                System.out.println("msg from server:" + str);
                SpringContextUtil.getBean(WebSocketProcess.class).sendAllMessage(str);
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

// 发送消息线程
class CSendMsgThread extends Thread {

    Socket response;

    public CSendMsgThread(Socket response) {
        this.response = response;
    }

    @Override
    public void run() {
        try {
            BufferedReader keyboardReader = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(response.getOutputStream()));
            String tempStr = "";
            while (!tempStr.contains("bye")) {
                tempStr = keyboardReader.readLine();
                // tempStr=URLEncoder.encode(tempStr, "UTF-8");//加码
                writer.write(tempStr + "\n");
                writer.flush();
            }
            System.out.println("结束会话!");
            keyboardReader.close();
            writer.close();
            response.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

客户端通过@Autowired注入的webSocketProcess为null,原因和解决方法在另一篇文章 点击这里 有写,这里我用SpringContextUtil这个工具类来获得webSocketProcess对象,工具类代码也会放在那里

socket服务端, 这里通过控制台输入,模拟socket服务端发消息,但到时候只需要客户端就可以:

@Component
public class ServerTestCommunicate {

    private static final int PORT = 1234;

    //public static void main(String[] args) {
    public static void start(String[] args) {
        try {
            ServerSocket server = new ServerSocket(PORT);
            new ReceiveMsgThread(server).start();// 开启消息接收

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void start() {
        start(null);
    }
}

// 处理接收消息的线程
class ReceiveMsgThread extends Thread {

    ServerSocket server;

    public ReceiveMsgThread(ServerSocket server) {
        this.server = server;

    }

    @Override
    public void run() {
        try {

            System.out.println("当前是服务器127.0.0.1窗口:");
            Socket response = server.accept();

            System.out.println("已有客户端连接:" + response.getInetAddress().getHostAddress());
            new SendMsgThread(response).start();// 连接上,开启发送线程
            BufferedReader reader = new BufferedReader(new InputStreamReader(response.getInputStream()));

            String str;
            while ((str = reader.readLine()) != null) {
                // str=URLDecoder.decode(str, "UTF-8");//解码
                System.out.println("msg from client:" + str);
            }

            //关闭
            reader.close();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

// 处理发送消息线程
class SendMsgThread extends Thread {

    Socket response;

    public SendMsgThread(Socket response) {
        this.response = response;
    }

    @Override
    public void run() {
        try {
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(response.getOutputStream()));
            BufferedReader keyboardReader = new BufferedReader(new InputStreamReader(System.in));

            // InputStreamReader in=new InputStreamReader(System.in, "UTF-8");

            String tempStr = "";
            while ((tempStr = keyboardReader.readLine()) != null) {

                // tempStr=URLEncoder.encode(tempStr, "UTF-8");//加码
                writer.write(tempStr + "\n");
                writer.flush();

            }
            System.out.println("结束会话!");

            response.close();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

主启动类里面让socket、服务端、客户端随项目运行

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class AppclientApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(AppclientApplication.class, args);
        context.getBean(ServerTestCommunicate.class).start();
        context.getBean(ClientTestCommunicate.class).start();

    }
}

websocket服务端:

@Slf4j
@Component
@ServerEndpoint(value = "/testWebSocket/{id}")
public class WebSocketProcess {

    /*
     * 持有每个webSocket对象,以key-value存储到线程安全ConcurrentHashMap,
     */
    private static ConcurrentHashMap<Long, WebSocketProcess> concurrentHashMap = new ConcurrentHashMap<>(12);

    /*private static WebSocketProcess webSocketProcess;
    @Autowired
    public void setWebSocketProcess(WebSocketProcess webSocketProcess) {
        WebSocketProcess.webSocketProcess = webSocketProcess;
    }*/
    /**
     * 会话对象
     **/
    private Session session;


    /*
     * 客户端创建连接时触发
     * */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") long id) {
        //每新建立一个连接,就把当前客户id为key,this为value存储到map中
        this.session = session;
        concurrentHashMap.put(id, this);
        log.info("Open a websocket. id={}", id);
    }

    /**
     * 客户端连接关闭时触发
     **/
    @OnClose
    public void onClose(Session session, @PathParam("id") long id) {
        //客户端连接关闭时,移除map中存储的键值对
        concurrentHashMap.remove(id);
        log.info("close a websocket, concurrentHashMap remove sessionId= {}", id);
    }

    /**
     * 接收到客户端消息时触发
     */
    @OnMessage
    public void onMessage(String message, @PathParam("id") String id) {
        log.info("receive a message from client id={},msg={}", id, message);
    }

    /**
     * 连接发生异常时候触发
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("Error while websocket. ", error);
    }

    /**
     * 发送消息到指定客户端
     *  @param id
     *  @param message
     * */
    public void sendMessage(long id, String message) throws Exception {
        //根据id,从map中获取存储的webSocket对象
        WebSocketProcess webSocketProcess = concurrentHashMap.get(id);
        if (!ObjectUtils.isEmpty(webSocketProcess)) {
            //当客户端是Open状态时,才能发送消息
            if (webSocketProcess.session.isOpen()) {
                webSocketProcess.session.getBasicRemote().sendText(message);
            } else {
                log.error("websocket session={} is closed ", id);
            }
        } else {
            log.error("websocket session={} is not exit ", id);
        }
    }

    /**
     * 发送消息到所有客户端
     *
     * */
    public void sendAllMessage(String msg) throws Exception {
        log.info("online client count={}", concurrentHashMap.size());
        Set<Map.Entry<Long, WebSocketProcess>> entries = concurrentHashMap.entrySet();
        for (Map.Entry<Long, WebSocketProcess> entry : entries) {
            Long cid = entry.getKey();
            WebSocketProcess webSocketProcess = entry.getValue();
            boolean sessionOpen = webSocketProcess.session.isOpen();
            if (sessionOpen) {
               // webSocketProcess.session.getBasicRemote().sendText(msg);
                webSocketProcess.session.getBasicRemote().sendText(msg);
            } else {
                log.info("cid={} is closed,ignore send text", cid);
            }
        }
    }

}

控制台模拟的socket服务端,输入,成功在前台输入框展示。
在这里插入图片描述

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Spring Boot整合WebSocket可以实现数据的实时更新推送前端。下面是实现的步骤: 1. 添加Spring Boot对WebSocket的支持 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建WebSocket处理器 创建一个WebSocket处理器类,继承自`TextWebSocketHandler`。这个处理器类会接收来自前端WebSocket请求,并处理WebSocket消息。 ``` public class MyWebSocketHandler extends TextWebSocketHandler { private List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) { sessions.add(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 处理WebSocket消息 } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { sessions.remove(session); } public void sendMessage(String message) { for (WebSocketSession session : sessions) { try { session.sendMessage(new TextMessage(message)); } catch (IOException e) { e.printStackTrace(); } } } } ``` 在上面的代码中,`afterConnectionEstablished()`方法会在建立WebSocket连接时被调用,`handleTextMessage()`方法会在接收到WebSocket消息时被调用,`afterConnectionClosed()`方法会在WebSocket连接关闭时被调用。`sendMessage()`方法用于向所有连接的WebSocket客户端发送消息。 3. 配置WebSocket 创建一个WebSocket配置类,用于配置WebSocket相关的内容。 ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myWebSocketHandler(), "/myWebSocketHandler").setAllowedOrigins("*"); } @Bean public MyWebSocketHandler myWebSocketHandler() { return new MyWebSocketHandler(); } } ``` 在上面的代码中,`registerWebSocketHandlers()`方法用于注册WebSocket处理器,`myWebSocketHandler()`方法返回我们创建的WebSocket处理器。 4. 发送消息到前端 在需要发送消息的地方,注WebSocket处理器,调用`sendMessage()`方法发送消息到前端。 ``` @Autowired private MyWebSocketHandler myWebSocketHandler; public void sendWebSocketMessage(String message) { myWebSocketHandler.sendMessage(message); } ``` 以上就是基于Spring Boot的WebSocket实现数据的实时更新推送前端的步骤。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值