Processing - how to send data (through websockets?

2019-02-04 04:01发布

问题:

I'm playing around with processing and wonder, if i can send data from processing to a javascript app. Is there any possibility to create a (e.g. websocket) server with processing?

Thanks in advance!

回答1:

I've tried Java WebSockets in eclipse for desktop(with or without extending PApplet) and it works on Android as well. If you want to use the library in Processing you need to do this:

  1. create a folder named java_websocket in Documents/Processing/libraries
  2. Inside the newly created java_websocket folder create another folder named library and drop java_websocket.jar there
  3. Restart Processing and start using the library (sketch > import library should list java_websocket now)

And here's the project sample code in processing: The server:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Collection;

import org.java_websocket.WebSocket;
import org.java_websocket.WebSocketImpl;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

void setup(){
  new ServerThread().start();
}
//create a separate thread for the server not to freeze/interfere with Processing's default animation thread
public class ServerThread extends Thread{
  @Override
  public void run(){
    try{
          WebSocketImpl.DEBUG = true;
          int port = 8887; // 843 flash policy port
          try {
            port = Integer.parseInt( args[ 0 ] );
          } catch ( Exception ex ) {
          }
          ChatServer s = new ChatServer( port );
          s.start();
          System.out.println( "ChatServer started on port: " + s.getPort() );

          BufferedReader sysin = new BufferedReader( new InputStreamReader( System.in ) );
          while ( true ) {
            String in = sysin.readLine();
            s.sendToAll( in );
          }
        }catch(IOException e){
          e.printStackTrace();
        }  
  }
}
public class ChatServer extends WebSocketServer {

  public ChatServer( int port ) throws UnknownHostException {
    super( new InetSocketAddress( port ) );
  }

  public ChatServer( InetSocketAddress address ) {
    super( address );
  }

  @Override
  public void onOpen( WebSocket conn, ClientHandshake handshake ) {
    this.sendToAll( "new connection: " + handshake.getResourceDescriptor() );
    System.out.println( conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!" );
  }

  @Override
  public void onClose( WebSocket conn, int code, String reason, boolean remote ) {
    this.sendToAll( conn + " has left the room!" );
    System.out.println( conn + " has left the room!" );
  }

  @Override
  public void onMessage( WebSocket conn, String message ) {
    this.sendToAll( message );
    System.out.println( conn + ": " + message );
  }

  @Override
  public void onError( WebSocket conn, Exception ex ) {
    ex.printStackTrace();
    if( conn != null ) {
      // some errors like port binding failed may not be assignable to a specific websocket
    }
  }

  /**
   * Sends <var>text</var> to all currently connected WebSocket clients.
   * 
   * @param text
   *            The String to send across the network.
   * @throws InterruptedException
   *             When socket related I/O errors occur.
   */
  public void sendToAll( String text ) {
    Collection<WebSocket> con = connections();
    synchronized ( con ) {
      for( WebSocket c : con ) {
        c.send( text );
      }
    }
  }
}

a test client:

import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.net.URI;
import java.net.URISyntaxException;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.java_websocket.WebSocketImpl;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_10;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.drafts.Draft_75;
import org.java_websocket.drafts.Draft_76;
import org.java_websocket.handshake.ServerHandshake;

void setup(){
  WebSocketImpl.DEBUG = true;
  new ChatClient( "ws://localhost:8887" );
}

public class ChatClient extends JFrame implements ActionListener {
  private static final long serialVersionUID = -6056260699202978657L;

  private final JTextField uriField;
  private final JButton connect;
  private final JButton close;
  private final JTextArea ta;
  private final JTextField chatField;
  private final JComboBox draft;
  private WebSocketClient cc;

  public ChatClient( String defaultlocation ) {
    super( "WebSocket Chat Client" );
    Container c = getContentPane();
    GridLayout layout = new GridLayout();
    layout.setColumns( 1 );
    layout.setRows( 6 );
    c.setLayout( layout );

    Draft[] drafts = { new Draft_17(), new Draft_10(), new Draft_76(), new Draft_75() };

    draft = new JComboBox( drafts );
    c.add( draft );

    uriField = new JTextField();
    uriField.setText( defaultlocation );
    c.add( uriField );

    connect = new JButton( "Connect" );
    connect.addActionListener( this );
    c.add( connect );

    close = new JButton( "Close" );
    close.addActionListener( this );
    close.setEnabled( false );
    c.add( close );

    JScrollPane scroll = new JScrollPane();
    ta = new JTextArea();
    scroll.setViewportView( ta );
    c.add( scroll );

    chatField = new JTextField();
    chatField.setText( "" );
    chatField.addActionListener( this );
    c.add( chatField );

    java.awt.Dimension d = new java.awt.Dimension( 300, 400 );
    setPreferredSize( d );
    setSize( d );

    addWindowListener( new java.awt.event.WindowAdapter() {
      @Override
      public void windowClosing( WindowEvent e ) {
        if( cc != null ) {
          cc.close();
        }
        dispose();
      }
    } );

    setLocationRelativeTo( null );
    setVisible( true );
  }

  public void actionPerformed( ActionEvent e ) {

    if( e.getSource() == chatField ) {
      if( cc != null ) {
        cc.send( chatField.getText() );
        chatField.setText( "" );
        chatField.requestFocus();
      }

    } else if( e.getSource() == connect ) {
      try {
        // cc = new ChatClient(new URI(uriField.getText()), area, ( Draft ) draft.getSelectedItem() );
        cc = new WebSocketClient( new URI( uriField.getText() ), (Draft) draft.getSelectedItem() ) {

          @Override
          public void onMessage( String message ) {
            ta.append( "got: " + message + "\n" );
            ta.setCaretPosition( ta.getDocument().getLength() );
          }

          @Override
          public void onOpen( ServerHandshake handshake ) {
            ta.append( "You are connected to ChatServer: " + getURI() + "\n" );
            ta.setCaretPosition( ta.getDocument().getLength() );
          }

          @Override
          public void onClose( int code, String reason, boolean remote ) {
            ta.append( "You have been disconnected from: " + getURI() + "; Code: " + code + " " + reason + "\n" );
            ta.setCaretPosition( ta.getDocument().getLength() );
            connect.setEnabled( true );
            uriField.setEditable( true );
            draft.setEditable( true );
            close.setEnabled( false );
          }

          @Override
          public void onError( Exception ex ) {
            ta.append( "Exception occured ...\n" + ex + "\n" );
            ta.setCaretPosition( ta.getDocument().getLength() );
            ex.printStackTrace();
            connect.setEnabled( true );
            uriField.setEditable( true );
            draft.setEditable( true );
            close.setEnabled( false );
          }
        };

        close.setEnabled( true );
        connect.setEnabled( false );
        uriField.setEditable( false );
        draft.setEditable( false );
        cc.connect();
      } catch ( URISyntaxException ex ) {
        ta.append( uriField.getText() + " is not a valid WebSocket URI\n" );
      }
    } else if( e.getSource() == close ) {
      cc.close();
    }
  }


}

That's pretty much pasted Java code which is verbose. But it should be easy to make some helper/wrapper classes if needed.

Doing a quick search returns these handy results:

  • Processing forum thread
  • PWS
  • Simple webcam with websockets and Processing
  • Processing over WebSocket

UPDATE

I've recently been introduced to a new Websockets library called spacebrew which is great for your inquiry, especially since they seem to have wrapped the java_websocket nicely behind the scenes.

Now you use this as any other Processing library, usage is greatly simplified(not java library experience needed, just Processing will do) and examples are great!

I got introduced to this through another question which allowed me to find out that it actually it works out of the box on your Android Device as well out of the box(just need to check the INTERNET box). How awesome is that ?

Getting all that sweet websocket action going on like it ain't no thing and bonus, it's android supported.

Quickly prototype on your desktop, then get your project working from your pocket.

Spacebrew ♥ Processing