美文网首页
websocket,用AI生成的,估计都是网上大神的代码,整合了

websocket,用AI生成的,估计都是网上大神的代码,整合了

作者: 晓晓_1931 | 来源:发表于2024-06-24 13:02 被阅读0次

    纯javaAPI (只能在控制台操作,没有界面)

    TestServerString

    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TestServerString {
    
        public static void main(String[] args) {
    
            try{
                //1.创建ServerSocket类型的对象并提供端口号
                ServerSocket ss = new ServerSocket(8888);
    
                //2.等待客户端的连接请求,调用accept()方法
                //实现服务器可以不断地响应客户端的连接请求
                while(true){
                    System.out.println("等待客户端的连接请求...");
                    //当没有客户端连接时,则阻塞在accept()方法的调用这里
                    //只要有客户端连接成功,则阻塞解除
                    Socket s = ss.accept();
                    System.out.println("客户端" + s.getInetAddress() + "连接成功!");
                    //每当有一个客户端连接成功,则开启一个新的线程为之服务
                    new ServerThread(s).start();
                }
                //ss.close();
            }catch(Exception e){
                e.printStackTrace();
            } 
        } 
    }
    

    TestClientString

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class TestClientString {
    
        public static void main(String[] args) {
    
            try{
                //1.构造Socket类型的对象并提供服务器的IP地址和端口号
                //Socket s = new Socket("XDL-20170621QCO", 8888);
                Socket s = new Socket("127.0.0.1", 8888);
                System.out.println("连接服务器成功!");
    
                //2.使用输入输出流进行通信
                Scanner sc = new Scanner(System.in);
                PrintStream ps = new PrintStream(s.getOutputStream());
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        s.getInputStream()));
    
                while(true){
                    //提示用户从键盘输入要发送的内容然后发送到服务器
                    System.out.println("请输入要发送的内容:");
                    String msg = sc.nextLine();
                    //让客户端向服务器发送字符串内容"hello"
                    //ps.println("hello");
                    ps.println(msg);
                    System.out.println("客户端发送数据成功!");
                    //当客户端向服务器发送"bye"后,则通信结束
                    if("bye".equalsIgnoreCase(msg)){
                        System.out.println("聊天结束");
                        break;
                    }
                    //实现客户端接收服务器发来的消息
                    String answer = br.readLine();
                    System.out.println("服务器回发的内容是:" + answer);
                }
    
                //3.关闭Socket
                br.close();
                ps.close();
                sc.close();
                s.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    
    }
    

    ServerThread

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.PrintStream;
    import java.net.Socket;
    
    public class ServerThread extends Thread {
        private Socket s;
    
        public ServerThread(Socket s){
            this.s = s;
        }
    
        @Override
        public void run(){
            try{
                //3.使用输入输出流进行通信
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        s.getInputStream()));
                PrintStream ps = new PrintStream(s.getOutputStream());
    
                while(true){
                    //System.out.println("等待客户端发送数据内容...");
                    //接收客户端发来的字符串内容并打印出来
                    String str = br.readLine();
                    //System.out.println("服务器接收到的消息是:" + str); //hello
                    System.out.println("客户端" + s.getInetAddress() + "说:" + str);
                    //当服务器接收到客户端发来的“bye”,则聊天结束
                    if("bye".equalsIgnoreCase(str)){
                        System.out.println("客户端" + s.getInetAddress() + "已下线!");
                        break;
                    }
                    //当服务器接收到客户端发来的内容向客户端回发消息"I received!"
                    ps.println("I received!");
                    //System.out.println("成功回发消息!");
                }
    
                //4.关闭Socket
                ps.close();
                br.close();
                s.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    

    vue+原生js WebSocket + javaWebSocket API

    1、后端pom.xml导入依赖

     <dependencies>
          <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.5.2</version>
          </dependency>
      </dependencies>
    

    2、后端TestServerWebSocket类

    import org.java_websocket.WebSocket;
    import org.java_websocket.handshake.ClientHandshake;
    import org.java_websocket.server.WebSocketServer;
    import java.net.InetSocketAddress;
    
    public class TestServerWebSocket extends WebSocketServer {
    
        public TestServerWebSocket(int port) {
            super(new InetSocketAddress(port));
        }
    
        @Override
        public void onOpen(WebSocket conn, ClientHandshake handshake) {
            System.out.println("客户端连接已打开");
        }
    
        @Override
        public void onClose(WebSocket conn, int code, String reason, boolean remote) {
            System.out.println("客户端连接已关闭");
        }
    
        @Override
        public void onMessage(WebSocket conn, String message) {
            System.out.println("从客户端接收到消息: " + message);
            // 向所有连接的客户端广播消息
            broadcast("hello");
        }
    
        @Override
        public void onError(WebSocket conn, Exception ex) {
            System.out.println("发生错误");
            ex.printStackTrace();
        }
    
        public static void main(String[] args) {
            try {
                TestServerWebSocket server = new TestServerWebSocket(8888);
                server.start();
                System.out.println("服务器启动在端口 8888");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void onStart() {
            
        }
    }
    

    3、vue + js原生WebSocket

    <template>
      <div>
        <h1>WebSocket 实时数据</h1>
        <ul>
          <input v-model="input">
          <button @click="sendMessage">发送</button>
          <p>{{ message }}</p>
        </ul>
      </div>
    </template>
    
    <script setup>
        import { ref } from 'vue'
        const socket = new WebSocket('ws://localhost:8888');
    
        socket.addEventListener('open', (event) => {
          console.log('WebSocket连接已打开', event);
        });
    
        socket.addEventListener('close', (event) => {
          console.log('WebSocket连接已关闭', event);
        });
    
        socket.addEventListener('error', (event) => {
          console.error('WebSocket发生错误:', event);
        });
    
        let message = ref('')
        socket.addEventListener('message', (event) => {
          // message = JSON.parse(event.data);
          message.value = event.data;
          console.log(message)
        });
    
        let input = ref('')
        function sendMessage() {
          socket.send(input.value);
          input.value = '';
        }
    </script>
    

    springboot+websocket

    依赖 pom.xml

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.3.RELEASE</version>
        </parent>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
    

    EchoChannel.java

    import java.io.IOException;
    import java.time.Instant;
    
    import javax.websocket.CloseReason;
    import javax.websocket.EndpointConfig;
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    // 使用 @ServerEndpoint 注解表示此类是一个 WebSocket 端点
    // 通过 value 注解,指定 websocket 的路径
    @ServerEndpoint(value = "/channel/echo")
    public class EchoChannel {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(EchoChannel.class);
    
        private Session session;
    
        // 收到消息
        @OnMessage
        public void onMessage(String message) throws IOException{
            
            LOGGER.info("[websocket] 收到消息:id={},message={}", this.session.getId(), message);
            
            if (message.equalsIgnoreCase("bye")) {
                // 由服务器主动关闭连接。状态码为 NORMAL_CLOSURE(正常关闭)。
                this.session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "Bye"));;
                return;
            }
            
            
            this.session.getAsyncRemote().sendText("["+ Instant.now().toEpochMilli() +"]" + new Random().nextInt());
        }
    
        // 连接打开
        @OnOpen
        public void onOpen(Session session, EndpointConfig endpointConfig){
            // 保存 session 到对象
            this.session = session;
            LOGGER.info("[websocket] 新的连接:id={}", this.session.getId());
        }
    
        // 连接关闭
        @OnClose
        public void onClose(CloseReason closeReason){
            LOGGER.info("[websocket] 连接断开:id={},reason={}", this.session.getId(),closeReason);
        }
    
        // 连接异常
        @OnError
        public void onError(Throwable throwable) throws IOException {
            
            LOGGER.info("[websocket] 连接异常:id={},throwable={}", this.session.getId(), throwable.getMessage());
            
            // 关闭连接。状态码为 UNEXPECTED_CONDITION(意料之外的异常)
            this.session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, throwable.getMessage()));
        }
    }
    

    WebSocketConfiguration.java

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
      
    @Configuration
    public class WebSocketConfiguration { 
        @Bean  
        public ServerEndpointExporter serverEndpointExporter(){ 
            ServerEndpointExporter exporter = new ServerEndpointExporter(); 
            // 手动注册 WebSocket 端点
            exporter.setAnnotatedEndpointClasses(EchoChannel.class); 
            return exporter;
        }  
    }
    

    前端vue(纯原生js websocket)

    <template>
      <div>
        <h1>WebSocket 实时通信</h1>
        <ul>
          <li v-for="(msg, index) in getMsg" :key="index">{{ msg }}</li>
        </ul>
      </div>
    </template>
    
    <script setup>
    import { ref } from 'vue'
    // 用来接收后端返回数据
    let getMsg = ref([])
    let websocket = new WebSocket("ws://localhost:8080/channel/echo");
    
    // 连接断开
    websocket.onclose = e => {
      console.log(`连接关闭: code=${e.code}, reason=${e.reason}`)
    }
    // 收到消息
    websocket.onmessage = e => {
      console.log(`收到消息:${e.data}`);
      // 接收后端发送的消息
      getMsg.value.push(e.data)
    }
    // 异常
    websocket.onerror = e => {
      console.log("连接异常")
      console.error(e)
    }
    
    // 连接打开
    websocket.onopen = e => {
      console.log("连接打开", e);
    
      // 创建连接后,往服务器没隔一秒连续写入1条消息 
      setInterval(sentData, 1000);
    
      function sentData() {
        websocket.send("hello")
      }
      // 最后发送 bye,由服务器断开连接
      // websocket.send("bye");
    
      // 也可以由客户端主动断开
      // websocket.close();
    }
    
    </script>
    

    以上代码后端是广播方式发送消息,想实现指定客户端返回数据,稍微修改一下以上EchoChannel 代码

    @ServerEndpoint(value = "/channel/echo")
    public class EchoChannel {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(EchoChannel.class);
    
        private Session session; 
        
        //用来记录不同客户端的sessionID,区分不同客户端
        private static final Map<String, Session> SESSION_MAP = new ConcurrentHashMap<>();
    
    
        // 收到消息
        @OnMessage
        public void onMessage(String message) throws IOException{
            String clientId = getClientIdFromSession(session);
            LOGGER.info("[websocket] 收到消息:clientId={},message={}", clientId, message);
            
            if (message.equalsIgnoreCase("bye")) {
                // 由服务器主动关闭连接。状态码为 NORMAL_CLOSURE(正常关闭)。
                this.session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "Bye")); 
                return;
            }
            System.out.println(clientId);
            if (clientId.equals("[10]")) {
                sendMessageToClient(clientId, "你是" + clientId + "号客户端");
            }
            if (clientId.equals("[20]")) {
                sendMessageToClient(clientId, "你好" + clientId + "号客户端");
            }
        }
    
        // 获取客户端id,用来识别是哪个客户端发送的消息
        private static String getClientIdFromSession(Session session) {
            String query = session.getRequestParameterMap().get("clientId").toString();
            return query != null ? query : "";
        }
        
        // 发送消息的逻辑
        public static void sendMessageToClient(String clientId, String message) {
            Session session = SESSION_MAP.get(clientId);
            if (session != null && session.isOpen()) {
                try {
                    session.getAsyncRemote().sendText(message);
                    LOGGER.info("[websocket] 发送给指定客户端:clientId={}, message={}", clientId, message);
                } catch (Exception e) {
                    LOGGER.error("[websocket] 发送消息异常:clientId={}, message={}, error={}", clientId, message, e.getMessage());
                    // 处理异常情况,可能需要移除无法通信的Session
                }
            } else {
                LOGGER.warn("[websocket] 尝试发送消息到不存在或已关闭的连接:clientId={}", clientId);
            }
        }
        
        // 连接打开
        @OnOpen
        public void onOpen(Session session, EndpointConfig endpointConfig){
             // 假设这里你有方法获取客户端的唯一标识,比如从session的属性中获取
            String clientId = getClientIdFromSession(session); // 实现这个方法来获取客户端ID 
            // 保存 session 到对象
            this.session = session;
            SESSION_MAP.put(clientId, session);
            LOGGER.info("[websocket] 新的连接:id={}, clientId={}", session.getId(), clientId);
        }
    
        // 连接关闭
        @OnClose
        public void onClose(CloseReason closeReason){
            String clientId = getClientIdFromSession(this.session); // 同样,确保实现这个方法
            SESSION_MAP.remove(clientId);
            LOGGER.info("[websocket] 连接断开:id={},reason={}, clientId={}", this.session.getId(), closeReason, clientId);
             
        }
    
        // 连接异常
        @OnError
        public void onError(Throwable throwable) throws IOException {
            
            LOGGER.info("[websocket] 连接异常:id={},throwable={}", this.session.getId(), throwable.getMessage());
            
            // 关闭连接。状态码为 UNEXPECTED_CONDITION(意料之外的异常)
            this.session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, throwable.getMessage()));
        }
    }
    

    客户端连接服务端的路径需要加上参数clientId

    "ws://localhost:8080/channel/echo?clientId=" + 10
    

    相关文章

      网友评论

          本文标题:websocket,用AI生成的,估计都是网上大神的代码,整合了

          本文链接:https://www.haomeiwen.com/subject/sdxdcjtx.html