Difference between revisions of "Tutorial: Client/Server on the Raspberry Pi"

From dftwiki3
Jump to: navigation, search
(Hardware Setup)
(Client Code to run on Windows)
 
(14 intermediate revisions by the same user not shown)
Line 11: Line 11:
 
<br />
 
<br />
 
=Hardware Setup=
 
=Hardware Setup=
<br /><center>[[Image:MacToRasberryConnection.png|400px]]</center>
+
<br /><center>[[Image:MacToRasberryConnection.png|700px]]</center>
 
<br />
 
<br />
 
* The setup is that proposed in the excellent blog page at http://pihw.wordpress.com/guides/direct-network-connection/  from which the image above is taken.
 
* The setup is that proposed in the excellent blog page at http://pihw.wordpress.com/guides/direct-network-connection/  from which the image above is taken.
 
* No need to try to copy what they already did very well, so simply follow their recommendations and connect your laptop to the Raspberry Pi using an ethernet cable.
 
* No need to try to copy what they already did very well, so simply follow their recommendations and connect your laptop to the Raspberry Pi using an ethernet cable.
 +
 +
<br />
 +
<br />
 +
<br />
 +
<br />
  
 
=Server/Client setup=
 
=Server/Client setup=
  
 
* Here we take another good example from [http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html User Moorthy] at [http://www.cs.rpi.edu RPI] and adapt it slightly for our use.
 
* Here we take another good example from [http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html User Moorthy] at [http://www.cs.rpi.edu RPI] and adapt it slightly for our use.
 
+
<br />
 +
<br />
 
==Server code==
 
==Server code==
 
<br />
 
<br />
Line 134: Line 140:
 
<br />
 
<br />
 
<br />
 
<br />
==Client code==
+
 
 +
==Client code to run on a Mac==
 
<br />
 
<br />
 
<br />
 
<br />
Line 143: Line 150:
 
Adapted from http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
 
Adapted from http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
 
The port number used in 51717.
 
The port number used in 51717.
This code is compiled and run on the Macbook laptop is below:
+
This code is compiled and run on the Macbook laptop as follows:
 
    
 
    
 
     g++ -o myClient myClient.c  
 
     g++ -o myClient myClient.c  
Line 227: Line 234:
 
<br />
 
<br />
 
<br />
 
<br />
 +
==Client Code to run on Windows==
 +
<br />
 +
S. L. Srinivas (slsrinivas12@gmail.com) offered this modified version for a Windows PC (Thanks for sharing!):
 +
<br />
 +
# Download & Install MinGW software to C:\MinGW. More info on MinGW can be found [http://mingw.org/ here].
 +
# Copy '''myClient.c''' to '''C:\MinGW\msys\1.0\bin'''
 +
#  Click on msys.bat located in the installed folder
 +
# Then in the '''msys.bat''' window type :
 +
#:
 +
#:  <tt>$ cd C:\MinGW\msys\1.0\bin</tt>
 +
#:
 +
# Then compile the C program using:
 +
#:
 +
#:  <tt>$ g++ -0 myClient myClient.c </tt>
 +
#:
 +
#: (which is similar to the way it is done on the Mac)
 +
# Then start the client:
 +
 +
:::<tt>  $ ./myClient</tt>
 +
 +
 +
Thats it, if the socket server is running, you should be able to see the data streaming in the msys.bat window.
 +
 +
==Typical Output==
 +
<br />
 +
The console outputs of the Server and of the Client are shown below:
 +
{|
 +
|
 +
Client Side
 +
./myClient
 +
contacting 169.254.0.2 on port 51717
 +
0 ->  0
 +
1 ->  2
 +
2 ->  4
 +
3 ->  6
 +
4 ->  8
 +
5 ->  10
 +
6 ->  12
 +
7 ->  14
 +
8 ->  16
 +
9 ->  18
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
|
 +
Server Side
 +
./myServer
 +
using port #51717
 +
waiting for new client...
 +
opened new communication with client
 +
got 0
 +
sending back 0
 +
got 1
 +
sending back 2
 +
got 2
 +
sending back 4
 +
got 3
 +
sending back 6
 +
got 4
 +
sending back 8
 +
got 5
 +
sending back 10
 +
got 6
 +
sending back 12
 +
got 7
 +
sending back 14
 +
got 8
 +
sending back 16
 +
got 9
 +
sending back 18
 +
got -1
 +
waiting for new client...
 +
 +
|}
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
[[Category:Tutorials]][[Category:Rasberry Pi]]

Latest revision as of 07:27, 21 September 2014

--D. Thiebaut (talk) 16:52, 8 July 2013 (EDT)


A simple example to get started. The Raspberry Pi runs a server that waits for connection from a laptop, and expects integers from it. It multiplies each integer by 2 and sends it back. The laptop runs a client that initiates a connection, sends a bunch of positive integers that it gets back multiplied by two, and closes the connection by sending a -1. Sending a -2 causes the server to stop.





Hardware Setup


MacToRasberryConnection.png


  • The setup is that proposed in the excellent blog page at http://pihw.wordpress.com/guides/direct-network-connection/ from which the image above is taken.
  • No need to try to copy what they already did very well, so simply follow their recommendations and connect your laptop to the Raspberry Pi using an ethernet cable.





Server/Client setup

  • Here we take another good example from User Moorthy at RPI and adapt it slightly for our use.



Server code


/* A simple server in the internet domain using TCP.
myServer.c
D. Thiebaut
Adapted from http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
The port number used in 51717.
This code is compiled and run on the Raspberry as follows:
   
    g++ -o myServer myServer.c 
    ./myServer

The server waits for a connection request from a client.
The server assumes the client will send positive integers, which it sends back multiplied by 2.
If the server receives -1 it closes the socket with the client.
If the server receives -2, it exits.
*/

#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>


void error( char *msg ) {
  perror(  msg );
  exit(1);
}

int func( int a ) {
   return 2 * a;
}

void sendData( int sockfd, int x ) {
  int n;

  char buffer[32];
  sprintf( buffer, "%d\n", x );
  if ( (n = write( sockfd, buffer, strlen(buffer) ) ) < 0 )
    error( const_cast<char *>( "ERROR writing to socket") );
  buffer[n] = '\0';
}

int getData( int sockfd ) {
  char buffer[32];
  int n;

  if ( (n = read(sockfd,buffer,31) ) < 0 )
    error( const_cast<char *>( "ERROR reading from socket") );
  buffer[n] = '\0';
  return atoi( buffer );
}

int main(int argc, char *argv[]) {
     int sockfd, newsockfd, portno = 51717, clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     int data;

     printf( "using port #%d\n", portno );
    
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
         error( const_cast<char *>("ERROR opening socket") );
     bzero((char *) &serv_addr, sizeof(serv_addr));

     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons( portno );
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
       error( const_cast<char *>( "ERROR on binding" ) );
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
  
     //--- infinite wait on a connection ---
     while ( 1 ) {
        printf( "waiting for new client...\n" );
        if ( ( newsockfd = accept( sockfd, (struct sockaddr *) &cli_addr, (socklen_t*) &clilen) ) < 0 )
            error( const_cast<char *>("ERROR on accept") );
        printf( "opened new communication with client\n" );
        while ( 1 ) {
	     //---- wait for a number from client ---
             data = getData( newsockfd );
             printf( "got %d\n", data );
             if ( data < 0 ) 
                break;
                
             data = func( data );

             //--- send new data back --- 
	     printf( "sending back %d\n", data );
             sendData( newsockfd, data );
	}
        close( newsockfd );

        //--- if -2 sent by client, we can quit ---
        if ( data == -2 )
          break;
     }
     return 0; 
}



Client code to run on a Mac



/* A simple client program to interact with the myServer.c program on the Raspberry.
myClient.c
D. Thiebaut
Adapted from http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
The port number used in 51717.
This code is compiled and run on the Macbook laptop as follows:
   
    g++ -o myClient myClient.c 
    ./myClient


*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h> 

void error(char *msg) {
    perror(msg);
    exit(0);
}

void sendData( int sockfd, int x ) {
  int n;

  char buffer[32];
  sprintf( buffer, "%d\n", x );
  if ( (n = write( sockfd, buffer, strlen(buffer) ) ) < 0 )
      error( const_cast<char *>( "ERROR writing to socket") );
  buffer[n] = '\0';
}

int getData( int sockfd ) {
  char buffer[32];
  int n;

  if ( (n = read(sockfd,buffer,31) ) < 0 )
       error( const_cast<char *>( "ERROR reading from socket") );
  buffer[n] = '\0';
  return atoi( buffer );
}

int main(int argc, char *argv[])
{
    int sockfd, portno = 51717, n;
    char serverIp[] = "169.254.0.2";
    struct sockaddr_in serv_addr;
    struct hostent *server;
    char buffer[256];
    int data;

    if (argc < 3) {
      // error( const_cast<char *>( "usage myClient2 hostname port\n" ) );
      printf( "contacting %s on port %d\n", serverIp, portno );
      // exit(0);
    }
    if ( ( sockfd = socket(AF_INET, SOCK_STREAM, 0) ) < 0 )
        error( const_cast<char *>( "ERROR opening socket") );

    if ( ( server = gethostbyname( serverIp ) ) == NULL ) 
        error( const_cast<char *>("ERROR, no such host\n") );
    
    bzero( (char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy( (char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
    serv_addr.sin_port = htons(portno);
    if ( connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) 
        error( const_cast<char *>( "ERROR connecting") );

    for ( n = 0; n < 10; n++ ) {
      sendData( sockfd, n );
      data = getData( sockfd );
      printf("%d ->  %d\n",n, data );
    }
    sendData( sockfd, -2 );

    close( sockfd );
    return 0;
}



Client Code to run on Windows


S. L. Srinivas (slsrinivas12@gmail.com) offered this modified version for a Windows PC (Thanks for sharing!):

  1. Download & Install MinGW software to C:\MinGW. More info on MinGW can be found here.
  2. Copy myClient.c to C:\MinGW\msys\1.0\bin
  3. Click on msys.bat located in the installed folder
  4. Then in the msys.bat window type :
    $ cd C:\MinGW\msys\1.0\bin
  5. Then compile the C program using:
    $ g++ -0 myClient myClient.c
    (which is similar to the way it is done on the Mac)
  6. Then start the client:
$ ./myClient


Thats it, if the socket server is running, you should be able to see the data streaming in the msys.bat window.

Typical Output


The console outputs of the Server and of the Client are shown below:

Client Side

./myClient
contacting 169.254.0.2 on port 51717
0 ->  0
1 ->  2
2 ->  4
3 ->  6
4 ->  8
5 ->  10
6 ->  12
7 ->  14
8 ->  16
9 ->  18














Server Side

./myServer
using port #51717
waiting for new client...
opened new communication with client
got 0
sending back 0
got 1
sending back 2
got 2
sending back 4
got 3
sending back 6
got 4
sending back 8
got 5
sending back 10
got 6
sending back 12
got 7
sending back 14
got 8
sending back 16
got 9
sending back 18
got -1
waiting for new client...