Tuesday, February 18, 2014

Full C++ Socket Server on Linux

There are many examples online as to how to construct one's own client / server socket connection in C++, but unfortunately they do kind of take for granted that you know your stuff. Here I will share my working source code which satisfied the questions I asked but could not find:

For this, I used Linux Mint 16 in VirtualBox with a Bridged Network Connection (my virtual machine had it's own IP address assigned by the local network router). Also used a C/C++ Eclipse IDE and the GCC Compiler, here is my server code: (the client side that tested this is in C# on the host OS, Windows 7)

#include <iostream>     // time, ctime
#include <cstdlib>      // exit
#include <cstdio>       // snprintf
#include <unistd.h>     // gethostname, write, close, sleep
#include <netdb.h>      // socket, htonl, htons
#define MAXHOSTNAME 256
void* memset(void* b, int c, size_t len);

int main()
{
  int listenfd = 0, connfd = 0, n;
  struct sockaddr_in serv_addr;
  const int BUFF = 32;
  char ioBuff[BUFF];

  // create socket and flush memory blocks

  listenfd = socket(AF_INET, SOCK_STREAM, 0);
  memset(&serv_addr, '0', sizeof(serv_addr));
  memset(ioBuff, '0', sizeof(ioBuff));

  // set socket properties

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0
  serv_addr.sin_port = htons(8080);

  // Initialize and start the socket

  bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
  listen(listenfd, 10);

  while(1)

  {
    // receive incoming connection
    connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

     do

     {
        // read data from client
        n = read(connfd, ioBuff, BUFF);
        ioBuff[BUFF-1] = (char)NULL; // terminate string
        std::cout << n << ": " << ioBuff;

        // write data to client

        write(connfd, ioBuff, BUFF);

            // continue to read and write until '-1' is received

     }while((int8_t)ioBuff[0] != -1);

     // close connection and repeat

     close(connfd);
     sleep(1);
  }
}

void* memset(void* b, int c, size_t len) {

    char* p = (char*)b;
    for (size_t i = 0; i != len; ++i) {
        p[i] = c;
    }
    return b;
}

For a full C++ server and client example, see this post on www.thegeekstuff.com.



Back Story
As part of the same project mentioned in my earlier post, GPIO, BeagleBone, and Bash, the next challenge was to communicate with the device over a network. The first choice that came to mind was the secure shell (SSH). I needed to communicate programmatically using my language of choice, C#.

I found SSH.NET and put something simple together. As excited as I may have been for a successful connection, I was now facing some serious LAG! (You know, the same lag everyone notices when playing Super Smash Bros. Brawl world wide?) It is time for alternatives!

C# doesn't exactly have many good SSH libraries out there for some odd reason. One of those weird outcomes of Microsoft. Nevertheless, all is not lost... I could still do this in C++ and then write a wrapper around that in C#. Success! Using libssh, a free open-source C++ library, I am sending SSH commands much more quickly.

(I need to use C# because I have a library written only in C# - no other language. Though I do now have the source code and could port it, this task would prove time consuming considering several hundred lines of code and then would need debugging and testing letter on - maybe better for a future project)

Just about finished here, several friends point out, using SSH for what I'm trying to accomplish is overkill! Since I am not sending commands through the global network but a local one, I should not need these layers of security. Instead, I should construct a simple socket connection. Benefits: I can get an even faster speed-boost, and I can write the socket client in C# while the socket server is all in C++!

With my trial run, as of today (Feb 18, 2014), I am very pleased with the results!

No comments:

Post a Comment