精华内容
下载资源
问答
  • 这是一个创建 websocket 服务器的程序(使用 runWebSocketProxy 运行)。 该服务器会将所有发送的消息广播给所有人(发送消息的人除外)。 该程序还会启动一个网络服务器(在端口 8888),显示当前文件夹中的所有...
  • 主要为大家详细介绍了java WebSocket实现聊天消息推送功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • java websocket框架

    2018-01-22 17:43:34
    demo,搭个tomcat就可以跑 长连接、websocket都支持,在多个浏览器测试通过
  • Java WebSocket爬虫实例

    2019-04-11 19:02:42
    一个基于JavaWebSocket爬虫示例,用于模拟客户端请求服务器,建立WebSocket连接,抓取对方数据,测试为某直播网站。运行时需要获取一个正在直播的网页地址,运行项目下的YizhiboView.java类。
  • 精通Java WebSocket应用开发 充分利用最先进的通信技术构建动态企业级Web应用。《Java WebSocket编程 开发、部署和保护动态Web应用》一书由Java WebSocket编程权威专家撰写,提供了实际的开发策略和详尽的示例应用...
  • java websocket简单DEMO

    2017-08-08 09:51:16
    java websocket简单DEMO 注解齐全
  • java websocket 1.3 jar

    2018-03-18 14:32:34
    java websocket 1.3 jarjava websocket 1.3 jarjava websocket 1.3 jarjava websocket 1.3 jar
  • java webSocket学习和Android端通信学习
  • Java WebSocket编程、开发、部署和保护动态Web应用 Java WebSocket编程、开发、部署和保护动态Web应用
  • java WebSocket所需jar包

    2017-11-10 14:49:12
    jar包中封装了有关WebSocket相关工具,可以利用注解很方便的实现WebSocket
  • Java WebSocket Programming

    2015-05-21 08:07:26
    Java WebSocket Programming - published by Oracle Press
  • java-websocket-客户端 一个简单的 java websocket 客户端。
  • 对于web开发人员迅速发展的工具箱而言,websocket是一种新的网络协议,被大量主流浏览器采用...
  • java websocket

    2016-08-18 14:43:00
    java websocket ,适合于Tomcat6.0+JDK1.6;Tomcat7.0的很好找,自己去百度,这个只是针对6.0 .下载完之,直接导入eclipse,配置server为Tomcat6.0 ,jdk为1.6,然后发布运行,输入...
  • java-websocket-reverse-proxy 我发现的大多数Java websocket示例都是基于或包含诸如STOMP之类的消息传递协议的。 该示例是研究如何代理任何消息内容而无需担心消息传递协议的结果。 Websocket反向代理的Java实现...
  • 导入工程运行即可,注意浏览器是否支持websocket.
  • 使用Java Websocket实时聊天室 服务器和客户端将通过websocket相互通信,消息以JSON文件的形式发送。 与http请求答案的机制不同,由于websocket是TCP协议,因此它将遵循3步握手模型。 websocket的标准协议对于常规...
  • web页面与java websocket接口的压力测试
  • java websocket 源码包

    2018-08-31 08:42:59
    这个源码包是android websocket的库,你可以在android上用这个做websocket,socketio服务器和客户端。网上可以下载到的。我是用这个来骗点积分的,没什么用
  • Java WebSocket Programming 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
  • 项目可以直接引入在MyEclipse,相关说明可以看本人博客
  • Java WebSocket爬虫

    千次阅读 2019-04-11 18:59:10
    因为这个,接触到了WebSocket技术,关于WebSocket基本知识的博客请参照这一篇Java WebSocket实例。 今天来总结一下如何利用java模拟客户端,与目标服务器建立WebSocket连接,抓取对方的数据。 需要的依赖: <...

    之前有个需求,要抓取某个网站视频的弹幕数据,坑爹的是它这个实时弹幕是基于WebSocket的。因为这个,接触到了WebSocket技术,关于WebSocket基本知识的博客请参照这一篇Java WebSocket实例

    今天来总结一下如何利用java模拟客户端,与目标服务器建立WebSocket连接,抓取对方的数据。

    需要的依赖:

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

    思路:主要就是继承WebSocketClient这个类,重写其中的onOpenonMessageonClose方法,通过onMessage方法,将数据保存至某个数据结构中。


    WebSocket功能类

    import org.java_websocket.WebSocket;
    import org.java_websocket.client.WebSocketClient;
    import org.java_websocket.handshake.ServerHandshake;
    
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.Iterator;
    
    public class MyWebSocketClient extends WebSocketClient{
    
      private WebSocketExecutor executor; // 用于保存获取的数据、判定是否需要关闭连接的功能类
    
      public MyWebSocketClient(String url,WebSocketExecutor executor) throws URISyntaxException {
        super(new URI(url));
        this.executor = executor;
      }
    
      @Override
      public void onOpen(ServerHandshake shake) {
        System.out.println("握手...");
        for(Iterator<String> it=shake.iterateHttpFields();it.hasNext();) {
          String key = it.next();
          System.out.println(key+":"+shake.getFieldValue(key));
        }
      }
    
      @Override
      public void onMessage(String paramString) {
        System.out.println("接收到消息:" + paramString);
        executor.doMessage(paramString);
        if(executor.needClose(paramString)){
          this.close();
          executor.setClose(true);
        }
      }
    
      @Override
      public void onClose(int paramInt, String paramString, boolean paramBoolean) {
        if (!executor.isClosed()) {
          executor.setClose(true);
        }
        System.out.println("关闭...");
      }
    
      @Override
      public void onError(Exception e) {
        System.out.println("异常"+e);
      }
    
    }
    

    自定义的WebSocket处理器

    import java.util.Queue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    /**
     * 自定义的WebSocket处理器
     * 用于保存或处理WebSocket数据
     * @author zfh
     * @version 1.0
     * @since 2019/4/2 16:26
     */
    public class MyWebSocketExecutor implements WebSocketExecutor{
    
        public Queue<String> msgQueue = new LinkedBlockingQueue<>();
    
        private Boolean isHasClosed = false;
    
        @Override
        public void doMessage(String msg) {
            msgQueue.add(msg);
        }
    
        @Override
        public boolean needClose(String msg) {
            return msgQueue.size() >= 1000;
        }
    
        @Override
        public void setClose(boolean close) {
            isHasClosed = close;
        }
    
        @Override
        public boolean isClosed() {
            return isHasClosed;
        }
    }
    
    

    测试

    以某直播平台为例进行测试(注:该网站可能会对消息改版,那样这个测试类可能就失效啦)

    运行该测试类还需要以下依赖:

    <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpclient</artifactId>
       <version>4.5.2</version>
    </dependency>
            
    <dependency>
       <groupId>cn.hutool</groupId>
       <artifactId>hutool-all</artifactId>
       <version>4.3.2</version>
    </dependency>
    

    测试类:

    package com.example.crawsocket.demo;
    
    import cn.hutool.json.JSONArray;
    import cn.hutool.json.JSONObject;
    import org.apache.http.Header;
    import org.apache.http.HeaderElement;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.util.EntityUtils;
    import org.java_websocket.WebSocket;
    
    import java.io.IOException;
    import java.net.URISyntaxException;
    import java.util.*;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * 一直播
     * 采集正在直播的实时弹幕,需要参数:直播url
     * @author zfh
     * @version 1.0
     * @since 2019/4/8 14:12
     */
    public class YizhiboView {
    
        private static String paramUrl = "http://app.yizhibo.com/com.yixia.im.accbal.api.ImAccBalService/1.0.0/getWebSocketConnAcces?_p=%7B%22_did%22%3A+%22undefined%22%2C%22_appid%22%3A+%2223%22%2C%22_pkgname%22%3A+%22h5.yizhibo.live%22%7D&scid=";
    
        /**
         * 获取WebSocket接收评论需要的参数
         * 包括:token和memberId
         * @param scid
         * @return
         */
        private static Map<String, String> getAccessParams(String scid) {
            Map<String, String> map = new HashMap<>();
            String url = paramUrl + "%22"+ scid + "%22"; // %22表示"
    
            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
            HttpGet get = new HttpGet(url);
    
            try {
                CloseableHttpResponse response = httpClient.execute(get);
                String res = EntityUtils.toString(response.getEntity());
                System.out.println(res);
                System.out.println("----------------");
                if (res != null && res.contains("imToken")) {
                    map.put("token", new JSONObject(res).getJSONObject("data").getStr("imToken"));
                }
                Header[] headers = response.getHeaders("Set-Cookie");
                if (headers != null && headers.length > 0) {
                    for (Header header : headers) {
                        HeaderElement[] elements = header.getElements();
                        if (elements != null && elements.length > 0) {
                            for (HeaderElement element : elements) {
                                System.out.println(element.getName() + ":" + element.getValue());
                                if (element.getName().equalsIgnoreCase("visitor_id")) {
                                    map.put("visitor_id", element.getValue());
                                }
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return map;
        }
    
        /**
         * 获取实时弹幕
         * @param scid
         * @param accessMap
         * @return
         */
        private static JSONArray getCommentList(String scid, Map<String, String> accessMap) {
            MyWebSocketExecutor executor = new MyWebSocketExecutor();
            try {
                MyWebSocketClient client = new MyWebSocketClient("wss://ws.yizhibo.com/websocket", executor);
                client.connect();
                while (!client.getReadyState().equals(WebSocket.READYSTATE.OPEN)) {
                    System.out.println("还没有打开");
                }
                System.out.println("建立websocket连接");
    
                client.send("{\"body\":\"{\\\"did_\\\":\\\"undefined\\\",\\\"isAnchor_\\\":\\\"0\\\",\\\"memberId_\\\":\\\"" + accessMap.get("visitor_id") + "\\\",\\\"token_\\\":\\\"" + accessMap.get("token") + "\\\",\\\"scid_\\\":\\\"" + scid + "\\\"}\",\"clientVersion\":101,\"cmdId\":2,\"isZip\":0}");
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
    
            while(!executor.isClosed()) {
                System.out.println("WebSocket未断开,继续接受数据中...");
                try {
                    Thread.sleep( 3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("共接受到数据: " + executor.msgQueue.size() + "条");
    
            return new JSONArray(executor.msgQueue);
        }
    
        /**
         * 提取正则匹配内容
         * @param regex
         * @param source
         * @return
         */
        private static String getMatcher(String regex, String source) {
            String result = "";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(source);
            while (matcher.find()) {
                result = matcher.group(1);
            }
            return result;
        }
    
    
        public static void main(String[] args) {
            String url = "https://www.yizhibo.com/l/17K5RkWx2nYxX4ii.html?p_from=Phome_HotAnchorRecommand"; // 可以去该直播网站官网随机获取一个正在直播的地址
            String scid = getMatcher("l/(.*).html", url);
            Map<String, String> accessMap = getAccessParams(scid);
            JSONArray array = getCommentList(scid, accessMap);
            System.out.println(array.toString());
        }
    }
    
    
    展开全文
  • java WebSocket客户端断线重连 | 实用代码框架

    万次阅读 多人点赞 2021-10-25 17:44:06
    在工作中是否会遇到实用websocket客户端连接服务端的时候,网络波动,服务端断连的情况。会导致客户端被动断开连接。为了解决这个问题,需要对被动断开连接的情况进行捕获,并重新创建连接。这篇文章主要是提供可以...

    目录

    前言

    Maven依赖

    代码

    总结


    前言

    在工作中是否会遇到实用websocket客户端连接服务端的时候,网络波动服务端断连的情况。会导致客户端被动断开连接。为了解决这个问题,需要对被动断开连接的情况进行捕获,并重新创建连接。这篇文章主要是提供可以直接使用的断线重连websocket客户端代码。

    Maven依赖

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.5.2</version>
            </dependency>
            <dependency>
                <groupId>org.java-websocket</groupId>
                <artifactId>Java-WebSocket</artifactId>
                <version>1.5.1</version>
            </dependency>

    代码

    不废话,上代码。

    package ai.guiji.csdn.ws.client;
    
    import cn.hutool.core.thread.ThreadUtil;
    import cn.hutool.core.util.StrUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.java_websocket.WebSocket;
    import org.java_websocket.client.WebSocketClient;
    import org.java_websocket.framing.Framedata;
    import org.java_websocket.handshake.ServerHandshake;
    
    import javax.net.ssl.*;
    import java.net.Socket;
    import java.net.URI;
    import java.nio.ByteBuffer;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicBoolean;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.function.Consumer;
    
    /** @Author huyi @Date 2021/10/15 20:03 @Description: 重连websocket客户端 */
    @Slf4j
    public class ReConnectWebSocketClient {
      /** 字符串消息回调 */
      private Consumer<String> msgStr;
      /** 字节流消息回调 */
      private Consumer<ByteBuffer> msgByte;
      /** 异常回调 */
      private Consumer<Exception> error;
      /** 连接标识 */
      private String key;
      /** ws服务端连接 */
      private URI serverUri;
      /** 尝试重连标识 */
      private AtomicBoolean tryReconnect;
      /** 需要ping标识 */
      private AtomicBoolean needPing;
      /** websocket连接实体 */
      private WebSocketClient webSocketClient;
      /** 重连次数 */
      private AtomicInteger reConnectTimes;
      /** 连接结束标识 */
      private AtomicBoolean end;
      /** 连接后初始发送报文,这里也可以不需要,如果服务端主动断开连接,重连后可以继续推送报文的话。 */
      private String initReConnectReq;
      /** 结束回调 */
      private Consumer<String> endConsumer;
    
      public ReConnectWebSocketClient(
          URI serverUri,
          String key,
          Consumer<String> msgStr,
          Consumer<ByteBuffer> msgByte,
          Consumer<Exception> error) {
        this.msgStr = msgStr;
        this.msgByte = msgByte;
        this.error = error;
        this.key = key;
        this.serverUri = serverUri;
        this.tryReconnect = new AtomicBoolean(false);
        this.needPing = new AtomicBoolean(true);
        this.reConnectTimes = new AtomicInteger(0);
        this.end = new AtomicBoolean(false);
        this.endConsumer = this::close;
        init();
      }
    
      /** 初始化连接 */
      public void init() {
        // 创建连接
        createWebSocketClient();
        // ping线程
        circlePing();
      }
    
      private void needReconnect() throws Exception {
        ThreadUtil.sleep(10, TimeUnit.SECONDS);
        int cul = reConnectTimes.incrementAndGet();
        if (cul > 3) {
          close("real stop");
          throw new Exception("服务端断连,3次重连均失败");
        }
        log.warn("[{}]第[{}]次断开重连", key, cul);
        if (tryReconnect.get()) {
          log.error("[{}]第[{}]次断开重连结果 -> 连接正在重连,本次重连请求放弃", key, cul);
          needReconnect();
          return;
        }
        try {
          tryReconnect.set(true);
    
          if (webSocketClient.isOpen()) {
            log.warn("[{}]第[{}]次断开重连,关闭旧连接", key, cul);
            webSocketClient.closeConnection(2, "reconnect stop");
          }
          webSocketClient = null;
          createWebSocketClient();
          connect();
          if (StrUtil.hasBlank(initReConnectReq)) {
            send(initReConnectReq);
          }
        } catch (Exception exception) {
          log.error("[{}]第[{}]次断开重连结果 -> 连接正在重连,重连异常:[{}]", key, cul, exception.getMessage());
          needReconnect();
        } finally {
          tryReconnect.set(false);
        }
      }
    
      private void createWebSocketClient() {
        webSocketClient =
            new WebSocketClient(serverUri) {
              @Override
              public void onOpen(ServerHandshake serverHandshake) {
                log.info("[{}]ReConnectWebSocketClient [onOpen]连接成功{}", key, getRemoteSocketAddress());
                tryReconnect.set(false);
              }
    
              @Override
              public void onMessage(String text) {
                log.info("[{}]ReConnectWebSocketClient [onMessage]接收到服务端数据:text={}", key, text);
                msgStr.accept(text);
              }
    
              @Override
              public void onMessage(ByteBuffer bytes) {
                log.info("[{}]ReConnectWebSocketClient [onMessage]接收到服务端数据:bytes={}", key, bytes);
                msgByte.accept(bytes);
              }
    
              @Override
              public void onWebsocketPong(WebSocket conn, Framedata f) {
                log.info(
                    "[{}]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode={}",
                    key,
                    f.getOpcode());
              }
    
              @Override
              public void onClose(int i, String s, boolean b) {
                log.info("[{}]ReConnectWebSocketClient [onClose]关闭,s={},b={}", key, s, b);
                if (StrUtil.hasBlank(s) || s.contains("https")) {
                  if (end.get()) {
                    return;
                  }
                  try {
                    needReconnect();
                  } catch (Exception exception) {
                    endConsumer.accept("reconnect error");
                    error.accept(exception);
                  }
                }
              }
    
              @Override
              public void onError(Exception e) {
                log.info("[{}]ReConnectWebSocketClient [onError]异常,e={}", key, e);
                endConsumer.accept("error close");
                error.accept(e);
              }
            };
        if (serverUri.toString().contains("wss://")) {
          trustAllHosts(webSocketClient);
        }
      }
    
      public void circlePing() {
        new Thread(
                () -> {
                  while (needPing.get()) {
                    if (webSocketClient.isOpen()) {
                      webSocketClient.sendPing();
                    }
                    ThreadUtil.sleep(5, TimeUnit.SECONDS);
                  }
                  log.warn("[{}]Ping循环关闭", key);
                })
            .start();
      }
    
      /**
       * 连接
       *
       * @throws Exception 异常
       */
      public void connect() throws Exception {
        webSocketClient.connectBlocking(10, TimeUnit.SECONDS);
      }
    
      /**
       * 发送
       *
       * @param msg 消息
       * @throws Exception 异常
       */
      public void send(String msg) throws Exception {
        this.initReConnectReq = msg;
        if (webSocketClient.isOpen()) {
          webSocketClient.send(msg);
        }
      }
    
      /**
       * 关闭
       *
       * @param msg 关闭消息
       */
      public void close(String msg) {
        needPing.set(false);
        end.set(true);
        if (webSocketClient != null) {
          webSocketClient.closeConnection(3, msg);
        }
      }
    
      /**
       * 忽略证书
       *
       * @param client
       */
      public void trustAllHosts(WebSocketClient client) {
        TrustManager[] trustAllCerts =
            new TrustManager[] {
              new X509ExtendedTrustManager() {
    
                @Override
                public void checkClientTrusted(
                    X509Certificate[] x509Certificates, String s, Socket socket)
                    throws CertificateException {}
    
                @Override
                public void checkServerTrusted(
                    X509Certificate[] x509Certificates, String s, Socket socket)
                    throws CertificateException {}
    
                @Override
                public void checkClientTrusted(
                    X509Certificate[] x509Certificates, String s, SSLEngine sslEngine)
                    throws CertificateException {}
    
                @Override
                public void checkServerTrusted(
                    X509Certificate[] x509Certificates, String s, SSLEngine sslEngine)
                    throws CertificateException {}
    
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
                    throws CertificateException {}
    
                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
                    throws CertificateException {}
    
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                  return null;
                }
              }
            };
    
        try {
          SSLContext ssl = SSLContext.getInstance("SSL");
          ssl.init(null, trustAllCerts, new java.security.SecureRandom());
          SSLSocketFactory socketFactory = ssl.getSocketFactory();
          client.setSocketFactory(socketFactory);
        } catch (Exception e) {
          log.error("ReConnectWebSocketClient trustAllHosts 异常,e={0}", e);
        }
      }
    
    }
    

    代码说明:

    1、参数的重连次数可以配置。

    2、增加异步pingpong线程,一旦结束连接会自动关闭。

    3、对字符串、字节流、异常都有回调措施。

    测试代码方法

      public static void main(String[] args) throws Exception {
        ReConnectWebSocketClient client =
            new ReConnectWebSocketClient(
                new URI(String.format("wss://192.168.1.77:24009")),
                "test",
                // 字符串消息处理
                msg -> {
                  // todo 字符串消息处理
                  System.out.println("字符串消息:" + msg);
                },
                null,
                // 异常回调
                error -> {
                  // todo 字符串消息处理
                  System.out.println("异常:" + error.getMessage());
                });
        client.connect();
        client.send("haha");
      }

    验证结果

    16:08:54.468 [WebSocketConnectReadThread-12] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onOpen]连接成功/192.168.1.77:24009
    16:08:54.475 [WebSocketConnectReadThread-12] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onMessage]接收到服务端数据:text=connect success from tcp4:192.168.6.63:11018!
    字符串消息:connect success from tcp4:192.168.6.63:11018!
    16:08:56.080 [WebSocketConnectReadThread-12] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onClose]关闭,s=,b=true
    16:09:06.097 [WebSocketConnectReadThread-12] WARN ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]第[1]次断开重连
    16:09:06.150 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onOpen]连接成功/192.168.1.77:24009
    16:09:06.150 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onMessage]接收到服务端数据:text=connect success from tcp4:192.168.6.63:11038!
    字符串消息:connect success from tcp4:192.168.6.63:11038!
    16:09:09.369 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:14.370 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:19.371 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:24.379 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:29.382 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:34.398 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:39.402 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:44.404 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:49.415 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:54.429 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:09:59.437 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:10:04.449 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:10:06.154 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:10:09.455 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:10:14.462 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:10:19.468 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onWebsocketPong]接收到服务端数据:opcode=PONG
    16:10:19.644 [WebSocketConnectReadThread-16] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onClose]关闭,s=,b=true
    16:10:29.654 [WebSocketConnectReadThread-16] WARN ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]第[2]次断开重连
    16:10:31.710 [WebSocketConnectReadThread-19] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onError]异常,e={}
    java.net.ConnectException: Connection refused: connect
    	at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
    	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    	at java.net.Socket.connect(Socket.java:589)
    	at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:673)
    	at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:461)
    	at java.lang.Thread.run(Thread.java:748)
    16:10:31.710 [WebSocketConnectReadThread-19] INFO ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]ReConnectWebSocketClient [onClose]关闭,s=error close,b=false
    异常:Connection refused: connect
    16:10:34.473 [Thread-0] WARN ai.guiji.csdn.ws.client.ReConnectWebSocketClient - [test]Ping循环关闭

    这里我才用的是手动关闭服务端方式触发,客户端被动断连情况。重连两次,第二次服务端还未启动导致异常触发。

    总结

    没啥好总结的,代码注释比较清楚。

    如果对你有用,一健三连走一波!

    展开全文
  • Java WebSocket客户端java WebSocketClient

    万次阅读 热门讨论 2018-01-09 17:52:31
    一、java客户端实现代码   package ggmes.websocket.client; import java.net.URI; import java.net.URISyntaxException;...import org.java_websocket.client.WebSocketClient; import org.ja...

    一、java客户端实现代码

     

    package ggmes.websocket.client;
    
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.Iterator;
    
    import org.java_websocket.client.WebSocketClient;
    import org.java_websocket.handshake.ServerHandshake;
    
    public class MsgWebSocketClient extends WebSocketClient{
    
    	public MsgWebSocketClient(String url) throws URISyntaxException {
    		super(new URI(url));
    		// TODO Auto-generated constructor stub
    	}
    
    	@Override
    	public void onOpen(ServerHandshake shake) {
    		// TODO Auto-generated method stub
    		System.out.println("握手...");
    		for(Iterator<String> it=shake.iterateHttpFields();it.hasNext();) {
    			String key = it.next();
    			System.out.println(key+":"+shake.getFieldValue(key));
    		}
    	}
    
    	@Override
    	public void onMessage(String paramString) {
    		// TODO Auto-generated method stub
    		System.out.println("接收到消息:"+paramString);
    	}
    
    	@Override
    	public void onClose(int paramInt, String paramString, boolean paramBoolean) {
    		// TODO Auto-generated method stub
    		System.out.println("关闭...");
    	}
    
    	@Override
    	public void onError(Exception e) {
    		// TODO Auto-generated method stub
    		System.out.println("异常"+e);
    		
    	}
    }
    


    二、单例初始化类:

     

     

    package ggmes.websocket.pusher;
    
    import java.net.URI;
    import java.net.URISyntaxException;
    
    import ggmes.websocket.client.MsgWebSocketClient;
    import ggmes.websocket.server.MsgWebSocketServer;
    import utils.ObjectUtils;
    
    public enum WebClientEnum {
    
    	CLIENT;
    	
    	private static MsgWebSocketClient socketClient = null;
    	
    	public static void initClient(MsgWebSocketClient client) {
    		socketClient = client;
    		if(ObjectUtils.isNotNull(socketClient)) {
    			socketClient.connect();
    			socketClient.send("测试websocket。。。");
    		}
    		boolean flag = true;
    		int i=1000;
    		while(flag) {
    			socketClient.send("测试websocket。。。"+(i--));
    			try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			if(i == 0) {
    				flag = false;
    			}
    		}
    	}
    	
    }
    


    三、启动主方法:

     

     

    package ggmes.websocket.bootstrap;
    
    
    import java.net.InetSocketAddress;
    import java.net.URISyntaxException;
    import java.util.HashMap;
    import java.util.Map;
    
    import ggmes.websocket.client.MsgWebSocketClient;
    import ggmes.websocket.pusher.WebClientEnum;
    import ggmes.websocket.pusher.WebServerEnum;
    import ggmes.websocket.server.MsgWebSocketServer;
    import play.mvc.Controller;
    
    public class SocketClientEngine{
    
    
    	public static void main(String[] args) {
    		try {
    			WebClientEnum.CLIENT.initClient(new MsgWebSocketClient("ws://192.168.152.73:8099"));
    		} catch (URISyntaxException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    

     

     

     

     

     

    展开全文
  • Java WebSocket 基础 消息通信

    千次阅读 2019-08-07 20:36:41
    为了发送WebSocket消息,无论注解式端点还是编程式端点,其API都是相同的:RemoteEndpoint和它的子类(RemoteEndpoint.Basic和RemoteEndpoint.Async)提供了发送消息的所有方法。 Ping和Pong消息通常被开发人员用来...

    为了发送WebSocket消息,无论注解式端点还是编程式端点,其API都是相同的:RemoteEndpoint和它的子类(RemoteEndpoint.Basic和RemoteEndpoint.Async)提供了发送消息的所有方法。

    Ping和Pong消息通常被开发人员用来检查WebSocket底层连接的健康性。
    从Session对象获得的RemoteEndpoint实例提供方法:

    public void sendPing(ByteBuffer applicationData) throws IOException, IllegalArgumentException;
    
    public void sendPong(ByteBuffer applicationData) throws IOException, IllegalArgumentException;
    
    • WebSocket规范定义了Ping和Pong消息可以传输125个字节大小的二进制数据
    • 调用这些方法时,如果传入的ByteBuffer参数超过了125个字节,则会抛出IllegalArgumentException异常
    • RemoteEndpoint接口和它的派生类中的所有发送消息的方法都会通过抛出IOException异常来表明在消息的传输过程中出现了错误

    1. 发送消息

    同步发送 RemoteEndpoint.Basic接口

    1.1 发送字符串消息
    //发送文本消息
    public void sendText(String text) throws IOException;
    
    //使用Writter API发送String消息
    public Writter getSendStream() throws IOException;
    
    //以分片的方式发送文本消息
    public void sendText(String partialMessage, boolean isLast) throws IOException;
    
    1.2 发送二进制消息
    //发送二进制消息
    public void sendBinary(ByteBuffer data) throws IOException;
    
    //分片发送二进制消息
    public void sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException;
    
    //使用流发送二进制消息
    public Outputstream getSendStream() throws IOException;
    
    1.3 发送对象消息
    //发送Java对象消息
    public void sendObject(Object data) throws IOException, EncodeException;
    

    Websocket是如何实现把对象编程WebSocket消息的,答案取决于你传什么类型的对象

    • 如果你传一个Java基本类型对象(或者其等值装箱类),则WebSocket实现会把数据转换成一个标准的Java字符串对象(使用toString()方法)
    • 如果传入的是其他对象,那么要为WebSocket实现提供一个javax.websocket.Encoder接口的实现
    public String encode(T object) throws EncodeException;
    
    public class DrawingEncoder implements Encoder.Text<DrawingObject> {
    
    	@Override
        public String encode(DrawingObject drawingObject) throws EncodeException {
        	...
        }
    
        @Override
        public void init(EndpointConfig endpointConfig) {}
    
        @Override
        public void destroy() {}
    }
    
    • javax.websocket.Encoder.Text<T>是最通用的接口,T就是想发送的对象类型(DrawingObject
    • 每次使用sendObject方法发送T类型的对象时,WebSocket实现都会调用相应的编码器,发给远程端点的实际是encode()方法返回的字符串
    • 如果你的编码器无法把指定对象转换成字符串,很可能会抛出EncodeException异常,在这种情形下,EncodeException将会传播给sendObject方法

    还可以灵活选择其他的Encoder接口

    • Encoder.TextStream<T> T转换成Writer
    • Encoder.Binary<T> T转换成ByteBuffer 对象编码成二进制消息
    • Encoder.CharacterStream<T>Encoder.BinaryStream<T> T转换成OutputStream 把对象编码成Java I/O流

    创建好编码器后,要选择如何在端点上配置它

    • 注解式:

      @ServerPoint(value = "/fruit", encoders = {MyAppleEncoder.class})
      public class ... {}
      
    • 编程式:

      //为编程式客户端端点配置编码器
      List<Class<? extends Encoder>> encoders = new ArrayList<>();
      encoders.add(MyAppleEncoder.class);
      ClientEndpointConfig config = ClientEndpointConfig.Builder.create().encoders(encoders).build();
      

      1

    2. 接收消息

    2.1 注解式端点接收消息
    //接收文本消息
    @OnMessage
    public void handleTextMessage(String textMessage) {
    	...
    }
    
    //接收二进制消息
    @OnMessage
    public void handleBinaryMessage(byte[] messageData) {
    	...
    }
    @OnMessage
    public void handleBinaryMessage(ByteBuffer messageData) {
    	...
    }
    
    //接收Pong消息,需要声明一个类型为 javax.websocket.PongMessage 的方法参数
    @OnMessage
    public String handlePongMessage(PongMessage pongMessage) {
    	return "I got " + pongMessage.getApplicationData().length + " bytes of data.";
    }
    
    //处理文本消息流
    @OnMessage
    public void handle(Reader message) {}
    //
    
    //处理到达的文本消息片段
    @OnMessage
    public void handlePartial(String textMessagePart, boolean isLast) {
    }
    
    //处理到达的二进制消息片段
    @OnMessage
    public void handlePartial(byte[] data, boolean isLast) {}
    @OnMessage
    public void handlePartial(ByteBuffer data, boolean isLast) {}
    

    把接收到的消息转换成Java对象,需要解码类
    提供Decoder接口的实现

    public class DrawingDecoder implements Decoder.Text<DrawingObject> {
        @Override
        public DrawingObject decode(String s) throws DecodeException {
            ...
        }
    
        @Override
        public boolean willDecode(String s) {
            ...
        }
    
        @Override
        public void init(EndpointConfig endpointConfig) {}
    
        @Override
        public void destroy() {}
    }
    
    • Decoder.Text<T> 把入站的文本消息转换成T类型的对象
    • willDecode 判断消息格式是否要用此解码

    还有其他类型的解码器

    • Decoder.TextStream<T> Reader转换成T
    • Decoder.Binary ByteBuffer转换成T
    • Decoder.BinaryStream InputStream转换成T
    • Java基本类型和它的等价类可以自动转换(Integer、Duble …)
      如果想解码的原始数据无法转换成期望的Java对象,将会抛出DecodeException异常。在所有这些解码失败中,引起失败的入站消息不会被传递,但解码器中产生的DecodeException异常会被传递给端点的错误处理方法。

    @OnMessage注解的方法的返回值类型决定了寄回消息给发送者的消息类型

    • 文本消息:String
    • 二进制消息:byte[] 或 ByteBuffer
    • 通过之前的转换规则,还可以响应标准Java基本类型及其等价类的文本信息(Integer、boolean …)

    Java WebSocket在接收消息上有一个严格的限制: 每个注解式端点最多只有一个消息处理方法处理每种本地WebSocket消息类型(即文本消息、二进制消息 和 Pong消息)

    例如:

    @ServerEndpoint(value = "/orchard", decoders = "{OrangeDecoder.class}")
    public class FruitTree {
    	@OnMessage
    	public void handleString(String message) {
    		...
    	}
    	
    	@OnMessage
    	public void handleOrange(Orange orange) {
    	 	...
    	}
    }
    
    • 假设OrangeDecoder 解码器实现了Decoder.Text<Orange> 或 Decoder.TextStream<T>中的任意一个,那么这个端点中就会有两个方法能够处理入站的文本消息,会部署失败,需要分到两个不同端点中。
    2.2 编程式端点接收消息

    编程式端点使用什么方式接收消息取决于MessageHandler接口和它的子类性

    public class ProgrammaticEchoServer extends Endpoint {
        @Override
        public void onOpen(Session session, EndpointConfig endpointConfig) {
            final Session mySession = session;
            mySession.addMessageHandler(new MessageHandler.Whole<String>() {
                @Override
                public void onMessage(String incomingMessage) {
                    try {
                        mySession.getBasicRemote().sendText("I got this (" + incomingMessage + ") so I am sending it back.");
                    } catch (IOException e) {
                        System.out.println("something went wrong:" + e.getMessage());
                    }
                }
            });
        }
    }
    
    • MessageHandler.Whole<String> 文本消息 String

    • MessageHandler.Whole<Reader> 文本消息 Java I/O流

    • MessageHandler.Whole<ByteBuffer> 二进制 Java NIO ByteBuffer

    • MessageHandler.Whole<byte[]> 二进制 Byte数组

    • MessageHandler.Whole<InputStream> 二进制 Java I/O流

    • MessageHandler.Partial<String> 文本片段 Java字符串序列

    • MessageHandler.Partial<ByteBuffer> 二进制片段 ByteBuffer序列

    • MessageHandler.Partial<byte[]> 二进制片段 字节数组序列

    • MessageHandler.Whole<T>Decoder.Text<T> 或者 Decoder.TextStream<T> 文本消息 对象类型T

    • MessageHandler.Whole<T>Decoder.Binary<T> 或者 Decoder.BinaryStream<T> 二进制消息 对象类型T

    //在编程式服务器端点中配置Decoder
    public class MyServerApplicationConfig implements ServerApplicationConfig {
        @Override
        public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> set) {
            Set<ServerEndpointConfig> configSet = new HashSet<>();
            List<Class<? extends Endpoint>> decoders = new ArrayList<>();
            decoders.add(MyOrangeDecoder.class);
            ServerEndpointConfig serverEndpointConfig = ServerEndpointConfig.Builder.create(MyEndpoint
            .class, "/fruit").decoders(decoders).build();
            configSet.add(serverEndpointConfig);
            return configSet;
        }
    
        @Override
        public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> set) {
            return set;
        }
    }
    
    

    限制条件与注解式相同,每个端点只允许最多一个方法来处理每个基本WebSocket消息类型。


    1. xxx ↩︎

    展开全文
  • java websocket proxy k8s docker terminal 之所以有这个项目是因为有多个区域部署k8s集群, 每个集群里的容器都需要有终端访问。 应用程序都是运行在k8s里的, 采用sa认证的方式, k8s集群的api server外面并不能...
  • WebSocket 的一个合适的类比是打电话。当打电话时,你通过拨号初始化一个电话呼叫。如果你尝试呼叫的人通过拿起话筒接受了呼叫,连接就已建立。当连接活跃时,如果乐意,双方可以同时说话(虽然并不推荐此种自由...
  • java实现websocket client

    2019-07-22 14:33:12
    java_websocket.jar最新jar包 可用java实现websocket客户端,使用demo: https://github.com/TooTallNate/Java-WebSocket/blob/master/src/main/example/ExampleClient.java

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 67,604
精华内容 27,041
关键字:

javawebsocket

java 订阅