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

jopen 10年前

使用Jetty,可以使用Java快速搭建一个Websocket Server。

快速创建Websocket Server

创建一个从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);  };

图像传输

功能:

  • 从网页中主动获取图像

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

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

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

代码修改

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

在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);          }      }
 

 来自:http://my.oschina.net/yushulx/blog/298140