Introduction To Computational Media (ICM) : Week 10

Client/Server

Server

Processing now supports the creation of network servers. Servers can accept socket connections from clients and can send and receive data from them.

Here is a simple server program that can accept any number of client connections in order to receive and send x and y coordinates from any of them:
            // Import the processing Net library
            import processing.net.*; 
            
            // Declare our server object
            Server myServer; 
            
            // X, Y and Previous X and Y coordinates
            int x = 0;
            int y = 0;
            int px = 0;
            int py = 0;
             
            void setup() 
            { 
              size(500, 500); 
              // Instantiate our server object, have it listen on port 10001
              myServer = new Server(this, 10001); 
            } 
             
            void draw() 
            { 
              // Create a client object if data is available to the server
              // This object references a client connection
              Client currentClient = myServer.available(); 
            
              // If the client isn't null, meaning that the client has data
              if (currentClient != null) 
              { 
                // Read the data from the client
                String XandY = currentClient.readString(); 
                
                // If the data is actually there
                if (XandY != null) 
                { 
                  println(currentClient.ip() + ": " + XandY); 
              
                  // Split the data on the ",", returning an array of strings
                  String[] sXandY = split(XandY,',');
                  // Convert the array of strings into an array of ints
                  int[] iXandY = int(sXandY);
                  
                  // If there is two values
                  if (iXandY.length == 2)
                  {
                    // Save our previous x and y values
                    px = x;
                    py = y;
                  
                    // assign our new values to x and y
                    x = iXandY[0];
                    y = iXandY[1];
            
                    println(x + " " + y);
                    // Display a line from the previous x and y to the new x and y values
                    line(x,y,px,py);
                    
                    // Send the new values to all of the clients
                    myServer.write(XandY);
                  }
                } 
              } 
            } 
        
Unfortunately, it is difficult to run a server as an applet (security restrictions and so on). Fortunately, you can run it from the Processing interface or from the "Export Application" functionality in Processing.

Server Example Application

Servers generally need to run on a machine that has a static IP address so clients know where to contact them. Also, Servers need to specify a network port on which to listen for a connection. Generally using a port in the 10000 or higher range is good practice as other more standard servers don't use them.

Client

Clients are programs that connect to servers to send and receive data.

Here is a client for the above server:
            // Import the Net library
            import processing.net.*; 
            
            // Declare a client object
            Client myClient; 
            
            // X, Y and Previous X and Y coordinates
            int x = 0;
            int y = 0;
            int px = 0;
            int py = 0;
             
            void setup() 
            { 
              size(500, 500); 
              // Instantiate the client, connect to "localhost" (the machine that this application is running on), port 10001
              myClient = new Client(this, "localhost", 10001); 
            } 
             
            void draw() 
            { 
              // If there is data available from the server
              if (myClient.available() > 0)
              {
                // Read the data and save in string
                String XandY = myClient.readString(); 
                
                // If the data isn't null
                if (XandY != null) 
                {                 
                  println("Read: " + XandY); 
            
                  // Split the data on the "," returning an array of strings
                  String[] sXandY = split(XandY,',');
                  // Convert our string array to an int array 
                  int[] iXandY = int(sXandY);
                  
                  // If we have two values
                  if (iXandY.length == 2)
                  {
                    // Set our previous x and y values to what we previously had saved in x and y
                    px = x;
                    py = y;
                    
                    // Set our x and y variables to our new data
                    x = iXandY[0];
                    y = iXandY[1];
            
                    println(x + " " + y);
                    
                    // Draw a line from the previous x and y to the new ones
                    line(x,y,px,py);
                  }
                } 
              } 
            } 
            
            void mousePressed()
            {
              // When the mouse is pressed we send our X and Y coordinates to the server
              myClient.write(mouseX + "," + mouseY);
            }        
        
Clients in the form of applets can only connect to servers that are running on the same machine that they are served from. Unfortunately, it is difficult to run a Processing server on the itp server so we are going to resort to using the client as an application as well.

Client Example Application

You can find out much more about both Clients and Servers from the Processing "Net" library documentation.

More Video/Image Processing

Dan O has a great series of examples working with video and images in a pixel by pixel manner: http://itp.nyu.edu/%7Edbo3/cgi-bin/ClassWiki.cgi?ICMVideo

Here is a more complex example that we can go through as well:

Remove Color from Video:
import processing.video.*;

Capture myImage;
color currentColor = color(255,255,255);
int threshold = 25;
int redColor = 255;
int blueColor = 255;
int greenColor = 255;
boolean reading = false;

void setup()
{
  size(320,240);
  frameRate(15);
  myImage = new Capture(this,width,height,15);
}

void draw()
{
    background(0);
    //myImage.loadPixels();
    
    reading = true;
    for(int row=0; row<myImage.height; row++) 
    { //for each row
      for(int col=0; col<myImage.width; col++) 
      { //for each column
        //get the color of this pixels
        //find pixel in linear array using formula: pos = row*rowWidth+column
      color pix = myImage.pixels[row*myImage.width+col]; 
      //find the difference
     if (red(pix) > redColor - threshold 
       && red(pix) < redColor + threshold
       && green(pix) > greenColor - threshold 
       && green(pix) < greenColor + threshold
       && blue(pix) > blueColor - threshold 
       && blue(pix) < blueColor + threshold)
       {
         myImage.pixels[row*myImage.width+col] = 0;
       } 
    }
  }
  //myImage.updatePixels();

  image(myImage,0,0);
  reading = false;
}

void mousePressed()
{
 currentColor = myImage.pixels[mouseY*myImage.width+mouseX];
 redColor = (int)red(currentColor);
 blueColor = (int)blue(currentColor);
 greenColor = (int)green(currentColor); 
}

void captureEvent(Capture video)
{
  if (reading == false)
  {
    video.read();
  }
}