Izza
Izza

Reputation: 2419

C++ Multithreaded TCP Server Issue

I'm writing a simple TCP server. The model that I though of is the server accepting client connections in the main thread and handing them over to another thread so that server can listen for connections again. The relevant parts of the code that I used are posted below:

Accepting connections:

void startServer () {

    int serverSideSocket = 0;
    int clientSideSocket = 0;

    serverSideSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSideSocket < 0) {
        error("ERROR opening socket");
        exit(1);
    }

    clientAddressLength = sizeof(clientAddress);
    memset((char *) &serverAddress, 0, sizeof(serverAddress));
    memset((char *) &clientAddress, 0, clientAddressLength);

    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    serverAddress.sin_port = htons(32000);

    if (bind(serverSideSocket, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
        error("ERROR on binding");
        exit(1);
    }      

    listen(serverSideSocket, SOMAXCONN);

    while(true) {
        clientSideSocket = accept(serverSideSocket, (struct sockaddr *) &clientAddress, &clientAddressLength);

    if (clientSideSocket < 0)
            error("ERROR on accept");

        processingThreadGroup->create_thread(boost::bind(process, clientSideSocket, this));
    }

}

Here, the processingThreadGroup is a boost::thread_group instance. In the process method:

void process (int clientSideSocket, DataCollector* collector) {

int numberOfCharactersRead = 0;
string buffer;

do {
      char msgBuffer[1000];
      numberOfCharactersRead = recv(clientSideSocket, msgBuffer, (1000 - 1), 0);
      if (numberOfCharactersRead < 0) {
          //display error
          close(clientSideSocket);
      }
      else if (numberOfCharactersRead == 0)
          close(clientSideSocket);
      else {
          printf("%s", msgBuffer);
          memset(msgBuffer, 0, 1000);
      }
   } while (numberOfCharactersRead > 0); 
}

However, when I debug the code, I saw that when the processing thread is invoked, the main thread is not accepting connections anymore. The data is read inside the process() method only. The main thread seem to be not running anymore. What is the issue with the approach I took and any suggestions to correct it?

EDIT: I think I found the issue here, and have updated it as an answer. Will not accept it since I answered my own question. Thank you for the help everyone!

Upvotes: 4

Views: 1493

Answers (1)

Izza
Izza

Reputation: 2419

Think I found the issue. I was using this as a server to accept syslog messages. The code I use for the syslog message generator is as follows:

openlog ("MyProgram", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL0);
cout << "opened the log" << endl;
for (int i = 0 ; i < 10 ; i++) 
{
    syslog (LOG_INFO, "Program started by User %d \n", getuid ());
    syslog (LOG_WARNING, "Beware of the WARNING! \n");
    syslog (LOG_ERR, "fatal ERROR! \n");
}   
closelog ();
cout << "closed the log" << endl;

and I use an entry in the rsyslog.conf file to direct all syslog LOG_LOCAL0 application traffic to be sent to the relevant TCP port where the server is listening. Somehow, syslog allows only one connection to be made, not multiple connections. Therefore, it only used one connection in a single thread. If that connection was closed, a new connection is craeted.

I checked with a normal tcp client. That works fine, with multiple threads being spawned for each connection accepted.

Upvotes: 1

Related Questions