目前要做人机交互界面的后台,人机对话内容需要实时展示在机器人屏幕上,人机对话的内容由语音系统推送到后台,用的是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服务端,输入,成功在前台输入框展示。

springboot默认tcp超时连接 springboot接收tcp数据_客户端