zoukankan      html  css  js  c++  java
  • 使用Jetty搭建Java Websocket Server,实现图像传输

    https://my.oschina.net/yushulx/blog/298140

    How to Implement a Java WebSocket Server for Image Transmission with Jetty

    创建一个从WebSocketHandler继承的类WSHandler

    import org.eclipse.jetty.websocket.api.Session;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
    import org.eclipse.jetty.websocket.api.annotations.WebSocket;
    import org.eclipse.jetty.websocket.server.WebSocketHandler;
    import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
     
    @WebSocket
    public class WSHandler extends WebSocketHandler {
     
        @OnWebSocketClose
        public void onClose(int statusCode, String reason) {
        }
     
        @OnWebSocketError
        public void onError(Throwable t) {
        }
     
        @OnWebSocketConnect
        public void onConnect(Session session) {
        }
     
        @OnWebSocketMessage
        public void onMessage(String message) {
        }
     
        @Override
        public void configure(WebSocketServletFactory factory) {
            // TODO Auto-generated method stub
            factory.register(WSHandler.class);
        }
    }
     

    设置一个端口和Handler,启动Server:

    public static void main(String[] args) throws Exception {
        Server server = new Server(2014);
        server.setHandler(new WSHandler());
        server.setStopTimeout(0);
        server.start();
        server.join();
    }
     

    JavaScript客户端

    写一个简单的测试。

    Index.htm:

    <!DOCTYPE html>
    <html>
        <body>
            <script src="websocket.js"></script>
        </body>
    </html>
     

    Websocket.js:

    var ws = new WebSocket("ws://127.0.0.1:2014/");
     
    ws.onopen = function() {
        alert("Opened");
        ws.send("I'm client");
    };
     
    ws.onmessage = function (evt) { 
    };
     
    ws.onclose = function() {
        alert("Closed");
    };
     
    ws.onerror = function(err) {
        alert("Error: " + err);
    };

    图像传输

    功能:

    • 从网页中主动获取图像

    • 服务端推送图像到网页中

    代码修改

    从网页中获取服务端数据。

    在index.htm中添加一个按钮元素和一个图片元素:

    <!DOCTYPE html>
    <html>
        <body>
            <h1>WebSocket Image Display</h1>
            <input type="button" id="button" value="image" ><br>
            <img id="image"></<img>
            <script src="websocket.js"></script>
        </body>
    </html>
     

    在Websocket.js中添加下面的代码:

    ws.binaryType = "arraybuffer";
    var button = document.getElementById("button");
    button.onclick = function() {
        ws.send("image"); // send the fetch request
    };
    ws.onmessage = function (evt) { // display the image
        var bytes = new Uint8Array(evt.data);
        var data = "";
        var len = bytes.byteLength;
        for (var i = 0; i < len; ++i) {
            data += String.fromCharCode(bytes[i]);
        }
        var img = document.getElementById("image");
        img.src = "data:image/png;base64,"+window.btoa(data);
    };

    服务端收到消息之后,发送图片:

    public void onMessage(String message) {
            System.out.println("Message: " + message);
            if (message.equals("image")) {
                System.out.println("session: " + mSession);
                if (mSession != null) {
                    try {
                        File f = new File("image\github.jpg");
                        BufferedImage bi = ImageIO.read(f);
                        ByteArrayOutputStream out = new ByteArrayOutputStream();
                        ImageIO.write(bi, "png", out);
                        ByteBuffer byteBuffer = ByteBuffer.wrap(out.toByteArray());
                        mSession.getRemote().sendBytes(byteBuffer);
                        out.close();
                        byteBuffer.clear();
     
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    从服务端发送数据到客户端。

    在服务端的UI上添加两个按钮,一个用来加载本地图片,一个用来发送图片:

    package com.ui;
     
    import java.awt.BorderLayout;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
     
    import javax.imageio.ImageIO;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFileChooser;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.filechooser.FileNameExtensionFilter;
     
    import com.server.WSHandler;
    import com.server.WebSocketServer;
     
    public class UIMain extends JPanel
                                 implements ActionListener {
        private JButton mLoad, mSend;
        private JFileChooser mFileChooser;
        private JLabel mImage;
        private byte[] mData;
        private WebSocketServer mWebSocketServer;
     
        public UIMain() {
            super(new BorderLayout());
     
            //Create a file chooser
            mFileChooser = new JFileChooser();
            FileNameExtensionFilter filter = new FileNameExtensionFilter(
                    ".png.jpg", "png","jpg");
            mFileChooser.setFileFilter(filter);
            mLoad = new JButton("Load");
            mLoad.addActionListener(this);
     
            mSend = new JButton("Send");
            mSend.addActionListener(this);
            mSend.setEnabled(false);
     
            // button panel
            JPanel buttonPanel = new JPanel(); 
            buttonPanel.add(mLoad);
            buttonPanel.add(mSend);
            add(buttonPanel, BorderLayout.PAGE_START);
     
            // image panel
            JPanel imageViewer = new JPanel();
            mImage = new JLabel();
            mImage.setSize(480, 640);
            imageViewer.add(mImage);
            add(imageViewer, BorderLayout.CENTER);
     
            // WebSocketServer
            mWebSocketServer = new WebSocketServer();
            mWebSocketServer.start();
        }
     
        @Override
        public void actionPerformed(ActionEvent e) {
     
        }
     
        private static void createAndShowGUI() {
            //Create and set up the window.
            JFrame frame = new JFrame("WebSocket Demo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
            //Add content to the window.
            frame.add(new UIMain());
     
            //Display the window.
            frame.pack();
            frame.setVisible(true);
            frame.setResizable(false);
            frame.setSize(480, 700);
     
            double width = Toolkit.getDefaultToolkit().getScreenSize().getWidth();
            double height = Toolkit.getDefaultToolkit().getScreenSize().getHeight();
            int frameWidth = frame.getWidth();
            int frameHeight = frame.getHeight();
            frame.setLocation((int)(width - frameWidth) / 2, (int)(height - frameHeight) / 2);
        }
     
        public static void main(String[] args) {
     
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    UIManager.put("swing.boldMetal", Boolean.FALSE); 
                    createAndShowGUI();
                }
            });
        }
    }
     

    为了防止UI阻塞,Websocket server需要在线程中创建:

    package com.server;
     
    import org.eclipse.jetty.server.Server;
     
    public class WebSocketServer extends Thread{
     
        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
     
            try {
                Server server = new Server(2014);
                server.setHandler(new WSHandler());
                server.setStopTimeout(0);
                server.start();
                server.join();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    在按钮事件中添加图片添加和发送功能:

    public void sendImage(byte[] data) {
            if (mSession == null)
                return;
     
            try {           
                ByteBuffer byteBuffer = ByteBuffer.wrap(data);
                mSession.getRemote().sendBytes(byteBuffer);
                byteBuffer.clear();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
    @Override
        public void actionPerformed(ActionEvent e) {
     
            if (e.getSource() == mLoad) {
     
                int returnVal = mFileChooser.showOpenDialog(UIMain.this);
     
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    File file = mFileChooser.getSelectedFile();     
     
                    // load image data to byte array
                    try {           
                        BufferedImage bi = ImageIO.read(file);
                        ByteArrayOutputStream out = new ByteArrayOutputStream();
                        ImageIO.write(bi, "png", out);
                        mData = out.toByteArray();
                        out.close();
                    } catch (IOException exception) {
                        exception.printStackTrace();
                    }
     
                    mImage.setIcon(new ImageIcon(mData));
                    mSend.setEnabled(true);
                }
            } 
            else if (e.getSource() == mSend) {
                ArrayList<WSHandler> sessions = WSHandler.getAllSessions();
                for (WSHandler session : sessions) {
                    session.sendImage(mData);
                }
                mSend.setEnabled(false);
            }
        }
     
  • 相关阅读:
    316. 去除重复字母
    331. 验证二叉树的前序序列化
    225. 用队列实现栈
    197. 上升的温度
    178. 分数排名
    177. 第N高的薪水
    小程序导航
    css3、js动画特效
    背景透明css
    h5新标签IE8不兼容怎么办?
  • 原文地址:https://www.cnblogs.com/donaldlee2008/p/5904871.html
Copyright © 2011-2022 走看看