Difference between revisions of "Tutorial: Client/Server on the Raspberry Pi"
(→Client Code to run on Windows) |
(→Client Code to run on Windows) |
||
Line 239: | Line 239: | ||
<br /> | <br /> | ||
# Download & Install MinGW software to C:\MinGW. More info on MinGW can be found [http://mingw.org/ here]. | # 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 | + | # Copy '''myClient.c''' to '''C:\MinGW\msys\1.0\bin''' |
# Click on msys.bat located in the installed folder | # Click on msys.bat located in the installed folder | ||
− | # Then in the | + | # Then in the '''msys.bat''' window type : |
+ | #: | ||
+ | #: <tt>$ cd C:\MinGW\msys\1.0\bin</tt> | ||
+ | #: | ||
# Then compile the C program using: | # Then compile the C program using: | ||
#: | #: |
Revision as of 06:26, 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.
Contents
Hardware Setup
- 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!):
- Download & Install MinGW software to C:\MinGW. More info on MinGW can be found 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 :
- $ cd C:\MinGW\msys\1.0\bin
- Then compile the C program using:
- $ g++ -0 myClient myClient.c
- (which is similar to the way it is done on the Mac)
- Then start the client:
- $ ./myClient
Thats it, if the socket server is running, you should be able to see the data streaming in the mays.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... |