Socket Tutorial
Contents
Socket Communication Tutorial with Elphel Cameras
This Tutorial will guide through creating a client - server communication framework example between a host computer and an Elphel camera using C.
This will only work under Linux!
Installing the Axis Compiler
The camera runs a kind of embedded Linux so we cannot use the normal (gcc) compiler for running our code on the camera but need a compiler for a specific target running environment.
Axis has a very comprehensive guide on installing and using their compiler.
Downloading and installing the compiler: http://developer.axis.com/wiki/doku.php?id=axis:compiler_install
This compile can take quite some time so make yourself a cup of tea or two.
The second guide on the Axis wiki is a short compile walkthrough: http://developer.axis.com/wiki/doku.php?id=axis:compiling_for_cris_howto, which we will cover later for our server source as well anyway.
Creating the Client Application
When referring to a client here I mean the computer which we will use to send requests to the camera.
Lets create a new file called client.c and paste the following code into it (thanks to the original creator):
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #define BUFFSIZE 32 void Die(char *mess) { perror(mess); exit(1); } int main(int argc, char *argv[]) { int sock; struct sockaddr_in echoserver; char buffer[BUFFSIZE]; unsigned int echolen; int received = 0; if (argc != 4) { fprintf(stderr, "USAGE: TCPecho <server_ip> <word> <port>\n"); exit(1); } /* Create the TCP socket */ if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { Die("Failed to create socket"); } /* Construct the server sockaddr_in structure */ memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */ echoserver.sin_family = AF_INET; /* Internet/IP */ echoserver.sin_addr.s_addr = inet_addr(argv[1]); /* IP address */ echoserver.sin_port = htons(atoi(argv[3])); /* server port */ /* Establish connection */ if (connect(sock, (struct sockaddr *) &echoserver, sizeof(echoserver)) < 0) { Die("Failed to connect with server"); } /* Send the word to the server */ echolen = strlen(argv[2]); if (send(sock, argv[2], echolen, 0) != echolen) { Die("Mismatch in number of sent bytes"); } /* Receive the word back from the server */ fprintf(stdout, "Received: "); while (received < echolen) { int bytes = 0; if ((bytes = recv(sock, buffer, BUFFSIZE-1, 0)) < 1) { Die("Failed to receive bytes from server"); } received += bytes; buffer[bytes] = '\0'; /* Assure null terminated string */ fprintf(stdout, buffer); } fprintf(stdout, "\n"); close(sock); exit(0); }
The next step requires a working compile environment. Make sure you have "build-essentials" package installed or otherwise get it with (typing in terminal):
sudo apt-get install build-essentials
Now we compile this the good old linux way by opening a terminal.
gcc client.c -o client.o
gcc is the compiler client.c is the source file we just created -o client.o defines where we we want the compiled output
If everything goes well there should now be a file called client.o in the same directory as the source file. If it did not work the compiler should have supplied one or more error messages.
To test the application we just compile now type:
./client.o
You should get an output like this:
USAGE: TCPecho <server_ip> <word> <port>
More about the usage later.
Creating the Server Application
Create another file called server.c and paste the following source code into it:
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #define MAXPENDING 5 /* Max connection requests */ #define BUFFSIZE 32 void Die(char *mess) { perror(mess); exit(1); } void HandleClient(int sock) { char buffer[BUFFSIZE]; int received = -1; /* Receive message */ if ((received = recv(sock, buffer, BUFFSIZE, 0)) < 0) { Die("Failed to receive initial bytes from client"); } /* Send bytes and check for more incoming data in loop */ while (received > 0) { /* Send back received data */ if (send(sock, buffer, received, 0) != received) { Die("Failed to send bytes to client"); } /* Check for more data */ if ((received = recv(sock, buffer, BUFFSIZE, 0)) < 0) { Die("Failed to receive additional bytes from client"); } } close(sock); } int main(int argc, char *argv[]) { int serversock, clientsock; struct sockaddr_in echoserver, echoclient; if (argc != 2) { fprintf(stderr, "USAGE: echoserver <port>\n"); exit(1); } /* Create the TCP socket */ if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { Die("Failed to create socket"); } /* Construct the server sockaddr_in structure */ memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */ echoserver.sin_family = AF_INET; /* Internet/IP */ echoserver.sin_addr.s_addr = htonl(INADDR_ANY); /* Incoming addr */ echoserver.sin_port = htons(atoi(argv[1])); /* server port */ /* Bind the server socket */ if (bind(serversock, (struct sockaddr *) &echoserver, sizeof(echoserver)) < 0) { Die("Failed to bind the server socket"); } /* Listen on the server socket */ if (listen(serversock, MAXPENDING) < 0) { Die("Failed to listen on server socket"); } /* Run until cancelled */ while (1) { unsigned int clientlen = sizeof(echoclient); /* Wait for client connection */ if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient, &clientlen)) < 0) { Die("Failed to accept client connection"); } fprintf(stdout, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr)); HandleClient(clientsock); } }