首页 > 代码库 > 使用Jetty搭建Java Websocket Server,实现图像传输

使用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; @WebSocketpublic 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);        }    }
 

使用Jetty搭建Java Websocket Server,实现图像传输