Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I would like to make non-block TCP receiver so the cilent can send message to server periodically (i.e. update information every 10 minutes).

I test it in a local machine. 'return_status' value indicates that the 'bind, accept, connect and write' are working correctly but the read always return -1. Can someone explain on this? Thanks

Code of client side.

#define CONTROLPORT 6000

int main(void)
{

int control_sock, return_status;
struct sockaddr_in control_addr;
socklen_t control_len;
memset(&control_addr, 0, sizeof(control_addr));
char control_message[10];

control_sock = socket(AF_INET, SOCK_STREAM, 0);

control_addr.sin_family = AF_INET;
control_addr.sin_addr.s_addr = inet_addr("192.168.16.133");
control_addr.sin_port = htons(CONTROLPORT);

return_status = bind(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));

fcntl(control_sock, F_SETFL, O_NONBLOCK); 

return_status = listen(control_sock, 1);
    cout << return_status << endl;
return_status = accept(control_sock, (struct sockaddr *) &control_addr, &control_len); 
    cout << return_status << endl;

while(1){

    return_status = read(control_sock,control_message,sizeof(control_message));

    cout << return_status << endl;

}







}

Code of sender side

#define CONTROLPORT 6000

using namespace std;

int main(void)
{

int control_sock, return_status;
struct sockaddr_in control_addr;
socklen_t control_len;
memset(&control_addr, 0, sizeof(control_addr));
char control_message[10];
control_message[10] = 111;

control_sock = socket(AF_INET, SOCK_STREAM, 0);

control_addr.sin_family = AF_INET;
control_addr.sin_addr.s_addr = inet_addr("192.168.16.133");
control_addr.sin_port = htons(CONTROLPORT);

return_status = connect(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));
    cout << return_status << endl;



    return_status = write(control_sock,control_message,sizeof(control_message));

    cout << return_status << endl;

}

share|improve this question
add comment

3 Answers

You have set your socket to non-blocking and as such accept is not going to block until some one connects. accept would be returning EAGAIN or EQOULDBLOCK. Check the errno. Without this checks your code proceeds to do the read. And it returns -1 (again check the errno) since the connections has not been established in the first place.

You have to use select, poll or epoll to see for events on non blocking sockets. That is to figure out if someone is connecting /sending data on established connections.

share|improve this answer
    
Thanks for your reply. I deleted the fcntl(control_sock, F_SETFL, O_NONBLOCK); The function "read' still return -1. At the mean while, the accept function returns 4. Seems like even I set it to blocking one, the problem remains exist. –  user3503150 Apr 25 at 7:59
add comment

If you're going to engage in non-blocking socket programming you have to understand that read() is going to return -1 with errno set to EAGAIN/EWOULDBLOCK when there is nothing to read, and use select() to tell you when it won't.

NB 4 is a valid socket FD in Unix, Solaris, HP-UX, AIDA, Linux, ...

share|improve this answer
add comment

In your situation, I don't think non-blocking server is necessary. If you really mean that, you should take a look at select(), epoll and the similar. As to your code, there're several problems:

  1. accept() in the server side should be in the while loop.
  2. accept() returns a descriptor for the accepted socket on success, and this descriptor should pass to read().
  3. As Prabhu's answer says, you have set your socket to O_NONBLOCK, so the accept() would return immediately. If no connections are present to be accepted, the errno would be set to EAGAIN or EWOULDBLOCK.

the code after modification:

int main(void)
{
    int control_sock, return_status;
    struct sockaddr_in control_addr;
    socklen_t control_len;
    memset(&control_addr, 0, sizeof(control_addr));
    char control_message[10];

    control_sock = socket(AF_INET, SOCK_STREAM, 0);

    control_addr.sin_family = AF_INET;
    control_addr.sin_addr.s_addr = inet_addr("192.168.7.134");
    control_addr.sin_port = htons(CONTROLPORT);

    return_status = bind(control_sock, (struct sockaddr *) &control_addr, sizeof(control_addr));

    //fcntl(control_sock, F_SETFL, O_NONBLOCK);

    return_status = listen(control_sock, 1);
    cout << return_status << endl;
    while(1){
        return_status = accept(control_sock, (struct sockaddr *) &control_addr, &control_len);
        cout << return_status << endl;


        return_status = read(return_status,control_message,sizeof(control_message));

        cout << return_status << endl;

    }
}
share|improve this answer
    
This is a part of program. I want to set non blocking so the program can enter the next broadcast functions. Basically I want to read the TCP data (if any) and send out UDP data next. Thanks for any further hints –  user3503150 Apr 25 at 10:26
    
not to mention the blocking and non-blocking, the most important part is you should read() the descriptor that the accept() returns in the server side. –  jfly Apr 25 at 13:21
    
Thanks for figuring this out. oh god how i read the return status. –  user3503150 Apr 25 at 22:32
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.