java websocket客户端 服务端demo

代码是 Java WebSocket;编程 开发、部署和保护动态Web应用书上的代码,自己加上了ping pong保活,修改作者的字符串分段发送为字节分块发送
MessagezModesServer

必须加@Component
具体原因 参考ServerEndpointExporter

@ServerEndpoint(value = "/modes")
@Component
public class MessagezModesServer {
    public static final int MESSAGE_MAX = 15 * 1024 * 1024;

    @OnOpen
    public void open(Session session){
        session.setMaxBinaryMessageBufferSize(MESSAGE_MAX);
        session.setMaxIdleTimeout(15000);
        reportMessage(session,"Connected !"+"\r\n");
    }

   /* @OnMessage
    public void testFixMessage(byte[] bytes,Session session){
        String report =  "Processed partial text message of size" + bytes.length +"b..."+"\r\n";
        reportMessage(session,report);
    }*/


    @OnMessage(
            maxMessageSize = MESSAGE_MAX
    )
    /**
     * 分块发送自定义的二进制数据,接收完统一处理
     */
    public void binaryMessage(byte[] bytes, boolean isLast, Session session) {
        String report = "Processed partial text message of size " + bytes.length + "b ...";
        System.out.println("isLast" + isLast);
        Map<String, Object> userProperties = session.getUserProperties();
        Object userData = userProperties.get("userData");
        if (userData == null){
            ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
            userProperties.put("userData", byteBuffer);
        }else {
            ByteBuffer byteBuffer = (ByteBuffer)userData;
            ByteBuffer allocate = ByteBuffer.allocate(byteBuffer.array().length + bytes.length);
            allocate.put(byteBuffer.array());
            allocate.put(bytes);
            userProperties.put("userData", allocate);
        }


        if (isLast) {
            report = report + "message complete." + "\r\n";
            ByteBuffer byteBuffer = (ByteBuffer)userProperties.get("userData");
            String s = new String(byteBuffer.array());
            System.out.println(s);
        }
        reportMessage(session, report);
    }

    /**
     * 一般直接把ping消息 直接返回
     * @param session
     * @param pm
     */
    @OnMessage
    public void handlePong(Session session,PongMessage pm){
        try {
            session.getBasicRemote().sendPong(pm.getApplicationData());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void reportMessage(Session session,String message){
        String format = DateFormat.getDateInstance().format(new Date());
        try {
            session.getBasicRemote().sendText(format + " " + message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @OnClose
    public void close(Session session, CloseReason cr){
        System.out.println(cr.getReasonPhrase());
    }

    @OnError
    public void error(Session session,Throwable throwable){
        System.out.println(throwable.getMessage());
    }


}

客户端代码
MessageModesClient

@ClientEndpoint
public class MessageModesClient {

    private Session session;

    private  MessageModesClientListener listener;

    private static class PartialMessageSendListener{
        public void reportProcess(int counter){
            System.out.println("当前是第 :"+counter +"块");
        }
        
    }

    private static class MessageModesClientListener {
        public void setConnected(boolean isCocnected,CloseReason cr){
             if (isCocnected){
                 System.out.println("连接已经打开");
             }else {
                 System.out.println("连接已经关闭 :" + cr.getReasonPhrase());
             }
        }


        public void reportConnectionHealth(long millis){
            System.out.println("ping pong 耗时毫秒数: "+millis);
        }

        public void reportMessage(String message){
            System.out.println("收到相应 :"+message);
        }
    }

    private class BinaryDataIterator{
        private byte[] data;
        private int chunk;//总数据块
        private int pos = 0;//第几块
        public BinaryDataIterator(byte[] data, int chunk) {
            this.data = data;
            this.chunk = chunk;
        }
        public boolean isLast(){
            return pos == chunk;
        }

        public boolean hasNext(){
            if (pos <= chunk-1 ){
                return true;
            }
            return false;
        }
        public byte[] next(){
            byte[] bytes = null;
            if (pos == chunk-1){
                bytes = Arrays.copyOfRange(data, pos * PIECES_COUNT, data.length);
                pos++;
            }else {
                bytes = Arrays.copyOfRange(data, pos * PIECES_COUNT, (pos + 1) * PIECES_COUNT);
                pos++;
            }
            return bytes;
        }
    }
    static int PIECES_COUNT = 53;

    private int sendTimeout = 10;

    public MessageModesClient(MessageModesClientListener listener){
        this.listener = listener;
    }

    public void setSendTimeout(int mills){
        this.sendTimeout = mills;
    }

    @OnOpen
    public void open(Session session){
        this.session = session;
        listener.setConnected(true,null);
        //TODO
    }

    @OnMessage
    public void handleMessage(String message){
        listener.reportMessage(message);
    }

    @OnMessage
    public void handlePong(PongMessage pm){
        String send = new String(pm.getApplicationData().array());
        long senTime = Long.parseLong(send);
        long roundtripMills = System.currentTimeMillis() - senTime;
        listener.reportConnectionHealth(roundtripMills);
    }

    @OnClose
    public void close(Session session,CloseReason cr){
          listener.setConnected(false,cr);
    }

    public void disconnect() throws IOException{
        this.session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE,"User close application"));
    }

    public void sendPing() throws IOException{
        long now = System.currentTimeMillis();
        byte[] data = ("" + now).getBytes();
        session.getBasicRemote().sendPing(ByteBuffer.wrap(data));
    }

    public Future<Void> sendAsyncFuture(byte[] data) throws IOException{
        RemoteEndpoint.Async asyncRemote = session.getAsyncRemote();
        asyncRemote.setSendTimeout(this.sendTimeout);
        ByteBuffer bb = ByteBuffer.wrap(data);
        return asyncRemote.sendBinary(bb);
    }

    public Future<Void> sendAsyncFuture(String data) throws IOException{
        RemoteEndpoint.Async asyncRemote = session.getAsyncRemote();
        asyncRemote.setSendTimeout(this.sendTimeout);
        return asyncRemote.sendBinary(ByteBuffer.wrap(data.getBytes()));
    }

    public void sendAsyncWithHandler(byte[] data,SendHandler sendHandler) throws IOException{
        RemoteEndpoint.Async asyncRemote = session.getAsyncRemote();
        asyncRemote.setSendTimeout(this.sendTimeout);
        asyncRemote.sendBinary(ByteBuffer.wrap(data),sendHandler);
    }

    public void sendAsyncStringWithHandler(String data,SendHandler sendHandler) throws IOException{
        RemoteEndpoint.Async asyncRemote = session.getAsyncRemote();
        asyncRemote.setSendTimeout(this.sendTimeout);
        asyncRemote.sendBinary(ByteBuffer.wrap(data.getBytes()),sendHandler);
    }

    public void sendSynchron(byte[] data) throws IOException{
        RemoteEndpoint.Basic basicRemote = session.getBasicRemote();
        basicRemote.sendBinary(ByteBuffer.wrap(data),true);
    }


    public void sendInPieces(byte[] message,PartialMessageSendListener partialMessageSendListener){
        RemoteEndpoint.Basic basicRemote = session.getBasicRemote();
        byte[] messageBytes = message;
        int chunkSize = (int)Math.ceil((double) messageBytes.length / PIECES_COUNT);

        BinaryDataIterator binaryDataIterator = new BinaryDataIterator(messageBytes,chunkSize);
        boolean isLast = false;
        int count = 1;
        while ((isLast = binaryDataIterator.hasNext())){
            byte[] next = binaryDataIterator.next();
            System.out.println("isLast "+binaryDataIterator.isLast() + next[0]);
            try {
                session.getBasicRemote().sendBinary(ByteBuffer.wrap(next),binaryDataIterator.isLast());
            } catch (IOException e) {
                e.printStackTrace();
            }
            partialMessageSendListener.reportProcess(count);
            count++;
        }

    }

    public static void main(String[] args) throws URISyntaxException, IOException, DeploymentException {
        WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
        MessageModesClient messageModesClient = new MessageModesClient(new MessageModesClientListener());
        webSocketContainer.connectToServer(messageModesClient, new URI("ws://127.0.0.1:22598/modes"));
        String data = "曹操以汉献帝刘协名义征讨四方 aaa !@#¥%*()";
        PartialMessageSendListener partialMessageSendListener = new PartialMessageSendListener();
        //messageModesClient.sendInPieces(data.getBytes(),partialMessageSendListener);
        //messageModesClient.sendSynchron(data.getBytes());
        /*messageModesClient.sendAsyncStringWithHandler(data, new SendHandler() {
            @Override
            public void onResult(SendResult result) {
                if (result.isOK()){
                    System.out.println("发送成功");
                }else {
                    System.out.println(result.getException());
                }

            }
        });*/

        Future<Void> voidFuture = messageModesClient.sendAsyncFuture(data);
        if (voidFuture.isDone()){
            System.out.println("发送成功");
        }
        Thread thread =  new Thread(){
            @Override
            public void run() {
                while (true){

                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    try {
                        messageModesClient.sendPing();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        thread.setDaemon(false);
        thread.start();
    }




}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值