Thread: Question about sockets in C

  1. #1
    Registered User
    Join Date
    Jun 2015
    Posts
    40

    Angry Question about sockets in C

    I have a few questions with regards to socket programming over Telnet/TCP in C:

    1. When I activate the client to access the program remotely it behaves normally however if I close down the terminal whilst the program is running, the last remote command issued decides to repeat itself until the program is terminated, how do is top this?
    2. When my program reaches the socket code i.e. my declared function below i can no longer operate my program manually/locally even if I don't have the client open. I have had a Google with this issue and the top result seems to be to do with the accept socket command blocking access. Note: I have tried to use non blocking sockets but still no luck. Also note that I would like my program to be able to be operated both manually/locally simultaneously even when the remote terminal is activated, and if possible if the program is controlled manually when the remote terminal is up to reflect the change on the remote terminal.
    3. And finally, I would like the ability to be able to type a word or phrase to activate a command rather than just a single character. If I enter a word instead of a character I get a multi character error and if I try double quotes it doesn't seem to respond to anything despite successfully compiling. From what I have heard you can use double quotes if you are programming in C++ but not C, however i have heard it is possible to use words to issue commands in C.

    I have posted my socket code below, I know the while(1) loop is a issue but this is the only thing currently preventing it from closing the connection. Also note that the remotecommand function is declared in my main program in an infinite loop but when ran none of the code after the declared function is ran despite closing the connection.

    Code:
    void sigchld_handler(int s)
    {
       while(waitpid(-1, NULL, WNOHANG) > 0);
    }
    
    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa)
    {
       if (sa->sa_family == AF_INET) {
          return &(((struct sockaddr_in*)sa)->sin_addr);
       }
    
       return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    
    
    int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
     int rc;
       struct addrinfo hints, *servinfo, *p;
       struct sockaddr_storage their_addr; // connector's address information
       socklen_t sin_size;
       struct sigaction sa;
       int yes=1;
       char s[INET6_ADDRSTRLEN];
       int rv;
       char recv_client_msg[100];
    
    
       memset(&hints, 0, sizeof hints);
       hints.ai_family = AF_UNSPEC;
       hints.ai_socktype = SOCK_STREAM;
       hints.ai_flags = AI_PASSIVE; // use my IP
    
       if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
          fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
          return 1;
       }
    
       // loop throui_pgh all the results and bind to the first we can
       for(p = servinfo; p != NULL; p = p->ai_next) {
          if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->arotocol)) == -1) {
             perror("server: socket");
             continue;
          }
    
          if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
                sizeof(int)) == -1) {
             perror("setsockopt");
             exit(1);
          }
    
          if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
             close(sockfd);
             perror("server: bind");
             continue;
          }
    
          break;
       }
    
       if (p == NULL)  {
          fprintf(stderr, "server: failed to bind\n");
          return 2;
       }
    
       freeaddrinfo(servinfo); // all done with this structure
    
       if (listen(sockfd, BACKLOG) == -1) {
          perror("listen");
          exit(1);
       }
    
       sa.sa_handler = sigchld_handler; // reap all dead processes
       sigemptyset(&sa.sa_mask);
       sa.sa_flags = SA_RESTART;
       if (sigaction(SIGCHLD, &sa, NULL) == -1) {
          perror("sigaction");
          exit(1);
       }
    
       int RemoteCommand(){  // main accept() loop
          sin_size = sizeof their_addr;
          new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
          if (new_fd == -1) {
             perror("accept");
          return(-1);    
          }
          //fcntl(sockfd, F_SETFL, O_NONBLOCK);
          //fcntl(new_fd, F_SETFL, O_NONBLOCK);
    
          inet_ntop(their_addr.ss_family,
             get_in_addr((struct sockaddr *)&their_addr),
             s, sizeof s);
          printf("server: got connection from %s\n", s);
    
          if (!fork()) { // this is the child process
          close(sockfd); // child doesn't need the listener
          if (send(new_fd, "Hello, world!", 13, 0) == -1)
          perror("send");       
    
       while(1) 
        {
          rc = read(new_fd, recv_client_msg, sizeof(recv_client_msg));
           if(write(new_fd,recv_client_msg, rc) <0 ) { printf("error writing to stream socket\n"); }
           if(recv_client_msg[0]=='1') {commandSwitch(1,1);}
           if(recv_client_msg[0]=='2') {commandSwitch(1,2);}
           if(recv_client_msg[0]=='3') {commandSwitch(2,1);}
           if(recv_client_msg[0]=='4') {commandSwitch(2,2);}   
         }
          close(new_fd);
             exit(0);
          }
          close(new_fd);  // parent doesn't need this
          return(0);
       }   
    //end of socket setup 
    This is my first use of sockets so please try and explain in detail what you mean should someone have a solution. I have posted this elsewhere and haven't found a solution.

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    When you read() from new_fd, you get the return value, and use it to write() on the next line, but you never check its value to see if it's <= 0. A zero condition means end-of-file, and negative means an error.

    You should really be using recv() and send() instead of read() and write().
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  3. #3
    Registered User
    Join Date
    Jun 2015
    Posts
    40
    Quote Originally Posted by Elkvis View Post
    When you read() from new_fd, you get the return value, and use it to write() on the next line, but you never check its value to see if it's <= 0. A zero condition means end-of-file, and negative means an error.

    You should really be using recv() and send() instead of read() and write().
    Someone wrote this on another forum, is this what you are referring to? and if so where exactly do I put it after the rc=? when i tried this from another forum i must have put it in the wrong place as the message was printed only when i opened the client before any issued commands.

    With regards to your specific comment, where will I type that? and would I have to define "true" as well does he mean the break; is at the end of the while or part of the else? the else doesn't have parenthesis around it that's all

    Code:
    rc = read(...);
    
    // At this point, we don't know if we have actually received anything
    
    if(rc <=0)
    {
        if(rc ==0)
            printf("Connection closed in a nice way by the other end\n");
        else
            fprintf(stderr,"Error reading: %s\n", strerror(errno));
    
        // Do note that not *all* errors are actually fatal,
        // For example: If you have non-blocking sockets then you
        // could have `errno == EWOULDBLOCK` and that's okay, and
        // means you should try to receive again in a little while
    
        break;// Break out of loop, let the connection be closed
    }
    
    // Now we *know* we have received something, process the data received
    // To be more precise, we have received `rc` byes of data
    Last edited by DA93; 06-16-2015 at 06:59 AM.

  4. #4
    Registered User
    Join Date
    Jun 2015
    Posts
    40
    Also may you have a solution for number 2). ?
    This is my most important of the 3 questions and is having the greatest impact in letting me progress?

  5. #5
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by DA93 View Post
    With regards to your specific comment, where will I type that? and would I have to define "true" as well does he mean the break; is at the end of the while or part of the else? the else doesn't have parenthesis around it that's all
    I think you're referring to my signature. It's attached to every message I post on this forum. Note the line above it, separating it from the post. You can ignore it.

    Quote Originally Posted by DA93 View Post
    Someone wrote this on another forum
    Cross-posting is not permitted on this forum. As you say, someone else already gave you that answer, meaning that the time I spent typing it was wasted. Please confine your inquiries to one forum at a time, and only post to another forum if you can't get answers here after an appropriate amount of time. When you give up in one place, please say so, and update the thread to show where else you're asking the question. It just makes it easier for forum users to keep track of which posts they should spend their time on.

    Quote Originally Posted by DA93 View Post
    is this what you are referring to? and if so where exactly do I put it after the rc=? when i tried this from another forum i must have put it in the wrong place as the message was printed only when i opened the client before any issued commands.

    Code:
    rc = read(...);
    
    // At this point, we don't know if we have actually received anything
    
    if(rc <=0)
    {
        if(rc ==0)
            printf("Connection closed in a nice way by the other end\n");
        else
            fprintf(stderr,"Error reading: %s\n", strerror(errno));
    
        // Do note that not *all* errors are actually fatal,
        // For example: If you have non-blocking sockets then you
        // could have `errno == EWOULDBLOCK` and that's okay, and
        // means you should try to receive again in a little while
    
        break;// Break out of loop, let the connection be closed
    }
    
    // Now we *know* we have received something, process the data received
    // To be more precise, we have received `rc` byes of data
    Yes, this would work. However, like I said, you should be using recv() instead of read() and send() instead of write(). It doesn't make much difference in your program, but recv() and send() are specifically designed to work with sockets, while read() and write() are general functions, intended to work on any file descriptor, and don't have the additional functionality that is sometimes required when working with sockets.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  6. #6
    Registered User
    Join Date
    Jun 2015
    Posts
    40
    sorry i should of ideally posted it saying 1 partially solved. I'll keep that in mind could you please link my code with modified rc code so I know exactly where to enter it, the lack of parenthesis doesn't help on the above "else". and can you show me send and recv implemented please? from my understanding its kind of the same but with flags. I should also mention when testing my program and came across these errors, messages were being printed on the terminal: 2 lines, one starting with "recv" and the second starting with "send" i honestly dont know where that came from because nowhere in my code do I have a print statement with send or recv in.

    Just to clarify your time wasn't wasted because I didn't understand what was meant by it and I posted it in two locations in an attempt to find a solution quicker
    Last edited by DA93; 06-16-2015 at 08:06 AM.

  7. #7
    Registered User
    Join Date
    Jun 2015
    Posts
    40
    and have you any idea on number 2? I have tried to get rid of the while and avoid the closing of the connection but error messages get printed. i thought that would solve my issue when i added the non blocking sockets but no luck.
    I assumed that no infinite while loop and a non blocking socket and the recv msg being in a function within a separate infinite loop would mean that the program would: start running into my infinite loop execute the beginning(which it does) then the declared function to check the connection, then exit the function and carry on the remainder of that infinite loop before looping back to the start again.
    However as said above in slightly less detail, even if I get rid of the while loop use NB sockets, the program doesn't advance past the point at which the function is declared even if i haven't opened the client and issued any commands. I'm frankly stumped, spent hours on this, hope I can get a solution soon.


    Thanks

  8. #8
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by DA93 View Post
    could you please link my code with modified rc code so I know exactly where to enter it, the lack of parenthesis doesn't help on the above "else".
    It goes immediately after you call read() or recv().

    Quote Originally Posted by DA93 View Post
    can you show me send and recv implemented please? from my understanding its kind of the same but with flags. I should also mention when testing my program and came across these errors, messages were being printed on the terminal: 2 lines, one starting with "recv" and the second starting with "send" i honestly dont know where that came from because nowhere in my code do I have a print statement with send or recv in.
    They take the same parameters as read() and write(), and in the same order, but with the additional flags parameter, which can be zero.

    Quote Originally Posted by DA93 View Post
    I posted it in two locations in an attempt to find a solution quicker
    Because you're selfish? Because you believe that your time is more valuable than mine? Because you think that you're too important to follow the forum rules, which you were instructed to read when you signed up?

    Quote Originally Posted by DA93 View Post
    and have you any idea on number 2?
    I don't even understand what you're asking in question number 2.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  9. #9
    Registered User
    Join Date
    Jun 2015
    Posts
    40
    In q2 i have something like this , in my main body:

    Code:
    for(;;) {  //infinite for loop repeat constantly
    //code here (execute beginning) 
    RemoteCommand();  //declared function above 
    // code here for remainder of infinite function
    }
    What I aim to achieve:
    1). when the program starts running the start of the infinite loop executes (does this already).
    2). Regardless if I'm accessing my program with the client or not i would still like the infinite for loop to complete so the program can also be operated manually whilst the client is still being accessed.(this doesn't work, when the program reaches the declared function in the for loop even if there is no remote access with the ip, the remainder of the for loop will NEVER execute: it happens even if i remove the while(1) loop from the function).
    3). So, if i start the program, i would like the program to operate as normal (as if the declared function wasn't there). Whilst being remotely accessed(accessing the port), I(if possible) would still like it to be operated manually as well. i.e. the function just checks for a connection and regardless if there is or isn't one it still continues the remainder of the for loop, NOT stay trapped inside that function.
    4) And one final point: if possible, for example if the above can be achieved, say i'm accessing the system remotely using TCP and someone makes a local change, the system feeds back to me that there has been a change locally.

    This is what i need to do for a project i am designing and i can't continue without it.
    Thanks

  10. #10
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    You should consider using non-blocking sockets, or using poll/select to check if the socket has events waiting. You can then interleave the socket code with your local control code, and allow control from both socket and local terminal/console. What operating system are you using? I'm guessing some variant of linux or some other posix-compliant OS.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  11. #11
    Registered User
    Join Date
    Jun 2015
    Posts
    40
    I am using Linux I raspbian Debian on the raspberry pi to control a system without the declared function I can operate it locally (using the code after the declared function at the end of the infinite for loop)

  12. #12
    Registered User
    Join Date
    Jun 2015
    Posts
    40
    I should add that I have implement the code already that's insufe the while(1) loop within the function into both a non blocking and select example. And on both occasions. No success, it still doesn't escape the function.

  13. #13
    Registered User
    Join Date
    Jun 2015
    Posts
    40
    I have to enter the commands after the listen and accept for it to work at all. Difference when o try NM non blocking sockets: it behaves the same, doesn't run competeley until remotely accessed and once accessed, it still responds to commands but difference being, whenever I'm not giving it a command it flags up a warning repeatedly.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Win32 API and sockets question.
    By Joelito in forum Windows Programming
    Replies: 0
    Last Post: 11-11-2009, 08:39 AM
  2. question about sockets
    By xixpsychoxix in forum Networking/Device Communication
    Replies: 2
    Last Post: 12-13-2007, 10:19 PM
  3. Sockets Transport Question
    By SMurf in forum Tech Board
    Replies: 0
    Last Post: 12-14-2006, 04:36 PM
  4. question about asynchronous sockets
    By pode in forum Networking/Device Communication
    Replies: 8
    Last Post: 12-27-2004, 02:33 PM
  5. Sockets Question
    By SyntaxBubble in forum Windows Programming
    Replies: 6
    Last Post: 12-30-2001, 07:50 AM

Tags for this Thread