0

Below is the basic client and server code . While iam trying to start an appliaction(which has to keep running in the machine once we send a msg to server) during connect call. using system(/bin/myApplication) in the client code (This basically is a simple c executable with an infinite loop,assuming my application has to be running); Once iam starting the application the server is in CLOSED_WAIT State and its coming back to listen only if i stop this application . The issue is with the server socket in CLOSED_WAIT state, Is there a way that this application keep running as a seperate process and server would be in listen state again. Client Code: There is a system command after read.and it starts an application(basically is an c executable with an infinite while loop)

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

int main(int argc, char *argv[])
{
    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in serv_addr; 

    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    } 

    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    } 

    memset(&serv_addr, '0', sizeof(serv_addr)); 

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000); 

    if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
    {
        printf("\n inet_pton error occured\n");
        return 1;
    } 

    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
       printf("\n Error : Connect Failed \n");
       return 1;
    } 

    while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
    {
        recvBuff[n] = 0;
        if(fputs(recvBuff, stdout) == EOF)
        {
            printf("\n Error : Fputs error\n");
        }
    } 
    system(/bin/myApplication);
    if(n < 0)
    {
        printf("\n Read error \n");
    } 

    return 0;

Server Code:

int main(int argc, char *argv[])
{
    int listenfd = 0, connfd = 0;
    struct sockaddr_in serv_addr; 

    char sendBuff[1025];
    time_t ticks; 

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

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(5000); 

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

    listen(listenfd, 10); 

    while(1)
    {
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); 

        ticks = time(NULL);
        snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
        write(connfd, sendBuff, strlen(sendBuff)); 

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

My Sample C File , which iam trying to execute using system command in client code. with

gcc Sample.c -o myApplication

int main(int argc, char *argv[])
{

    while(1)

    {

    }
}

I have tried using fork , but still the socket is in same state , is there anyway that this application runs seperately and doesnt effect the socket nor does it depend on the parent process(Server here).

user2256825
  • 594
  • 6
  • 22
  • In your client, close sockfd before launching your app via system(). Why do you need to keep it open? If your server is not accepting multiple connections, the problem is elsewhere in your code. – arayq2 Nov 27 '15 at 22:57

2 Answers2

0

Your client app never closes the socket, and since the sample app you spawn loops forever, the client never exits. This leaves the TCP connection state hanging on both sides.

In the client, try closing the socket before spawning the sample app.

Also, I think you're confused about the TCP states. A server endpont in the LISTEN state does not transition to CLOSE_WAIT and back. The LISTEN endpoint (the socket you called listen() on) will stay in that state until closed. The connected endpoint (the socket returned by accept()) will transition through various states during its lifetime.

If you're using the netstat command to see the states, be sure to use the -a flag to display the listening endpoints as well.

keithmo
  • 4,893
  • 1
  • 21
  • 17
  • But, This is holding the connection ans my client is nt able to connect to server till i kill the application. Also, Is there a way that TCP connection gets closed . I mean can we start a new process that doesnt effect the connection. – user2256825 Nov 27 '15 at 20:01
  • It just ran this locally (OSX) and it works fine (after a few minor changes to make it compile). I can start multiple clients and they all connect to the server, retrieve the timestamp string, then spawn the "app". What are the EXACT steps you do to see the problem? – keithmo Nov 27 '15 at 20:50
  • i works fine and multiple clients are running, but for all these connections the port is in CLOSED_WAIT state, if we do netstat -apn | grep 5000. i was looking for a way (a seprate process for the application) which doesnt effect the port and even it gets closed propely , though the application is running. AS OF NOW, THE APPLICATION HAS TO E CLOSED FOR ENDING THE CONNECTION. – user2256825 Nov 28 '15 at 07:34
  • As I wrote in my answer, your client does not close its socket. Add a `close(sockfd);` **before** the call to `system("/bin/myApplication");` and the CLOSED_WAIT goes away. I just verified this under OSX (10.11.1) and Linux (Debian 7.9). – keithmo Nov 28 '15 at 15:36
  • Reference Link : http://stackoverflow.com/questions/6945865/process-started-from-system-command-in-c-inherits-parent-fds – user2256825 Nov 30 '15 at 14:39
  • can someone suggest what has to be done if we do not have the socket file descriptor , is there a way that i can stop inheriting the parents file descriptors without knowing ? – user2256825 Dec 01 '15 at 13:26
0

I added the below line before the system command

fcntl(sockfd, F_SETFD, fcntl(sockfd, F_GETFD) | FD_CLOEXEC);

And Changed my client code to

#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in serv_addr;

    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    }

    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000);

    if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
    {
        printf("\n inet_pton error occured\n");
        return 1;
    }

    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
       printf("\n Error : Connect Failed \n");
       return 1;
    }

    while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
    {
        recvBuff[n] = 0;
        if(fputs(recvBuff, stdout) == EOF)
          printf("\n Error : Fputs error\n");
        }

   }

        fcntl(sockfd, F_SETFD, fcntl(sockfd, F_GETFD) | FD_CLOEXEC);

         system("/software/itcsm/itcsm/refasset/bin/start_script.sh 1");

    if(n < 0)
    {
        printf("\n Read error \n");
    }
        printf("\n after system \n");

    return 0;
}

By default whenever we fork a process (which system command does), the child inherits all the parent's file descriptors. If the child doesn't need those descriptors, it SHOULD close them voluntarily on file descriptor using fcntl(sockfd, F_SETFD, fcntl(sockfd, F_GETFD) | FD_CLOEXEC);

user2256825
  • 594
  • 6
  • 22