Thread: nonblocking sockets C

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    4

    nonblocking sockets C

    Hello.
    Pre forgive me for my English
    my program (using non blocking sockets) should connect to server, send string and async recieve replies form server.
    but it cant connect to server
    Code:
    #include <stdio.h>      /* for printf(), fprintf() */
    #include <winsock2.h>    /* for socket(),... */
    #include <stdlib.h>     /* for exit() */
    #include <time.h>
    #include <sys/types.h>
    
    #define RCVBUFSIZE 32   /* Size of receive buffer */
    
    void DieWithError(char *errorMessage){
        perror(errorMessage);
        exit(0);
    };  /* Error handling function */
    
    void main(int argc, char *argv[])
    {
        int sock, rc;                        /* Socket descriptor */
        struct sockaddr_in echoServAddr; /* Echo server address */
        unsigned short echoServPort;     /* Echo server port */
        //char *servIP;                    /* Server IP address (dotted quad) */
        char servIP[] = "10.42.43.1";
    	char echoString[]= "identifier=1z2y3z \r\n\r\n";
        char echoBuffer[RCVBUFSIZE];     /* Buffer for echo string */
        int echoStringLen;               /* Length of string to echo */
        int bytesRcvd, totalBytesRcvd;   /* Bytes read in single recv() and total bytes read */
        WSADATA wsaData;                 /* Structure for WinSock setup communication */
        unsigned long nonblocking = 1;
    	fd_set writefds, readfds;
    	struct timeval tv;
        tv.tv_sec = 5;
        tv.tv_usec = 500000;
        //servIP =  argv[1];             /* First arg: server IP address (dotted quad) */
        echoServPort = 8088; //atoi(8088);  //atoi(argv[2]);  /* Use given port, if any */
        if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) /* Load Winsock 2.0 DLL */
        {
            fprintf(stderr, "WSAStartup() failed");
            exit(1);
        }
    
        /* Create a reliable, stream socket using TCP */
        if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) < 0)
            DieWithError("socket() failed");
       
    
        /* Set the socket to nonblocking */
        if (ioctlsocket(sock, FIONBIO, &nonblocking) != 0)
            DieWithError("ioctlsocket() failed");
    
        /* Construct the server address structure */
        memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
        echoServAddr.sin_family      = AF_INET;             /* Internet address family */
        echoServAddr.sin_addr.s_addr = inet_addr(servIP);   /* Server IP address */
        echoServAddr.sin_port        = htons(echoServPort); /* Server port */
        
        FD_ZERO(&writefds);
        FD_SET(sock, &writefds);
    	rc = select(sock, NULL, &writefds, NULL, &tv);
    	if((rc == 1) && (FD_ISSET(sock, &writefds)))
    {
    	/* Establish the connection to the echo server */
        if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
    		DieWithError("connect() failed");
    	}
    	
        echoStringLen = strlen(echoString);          /* Determine input length */
    
    	FD_ZERO(&readfds);
        FD_SET(sock, &readfds);
    	rc = select(sock, &readfds, NULL, NULL, &tv);
    	if((rc == 1) && (FD_ISSET(sock, &readfds)))
        {
        /* Send the string, including the null terminator, to the server */
        if (send(sock, echoString, echoStringLen, 0) != echoStringLen)
            DieWithError("send() sent a different number of bytes than expected");
    	}
        /* Receive the same string back from the server */
        totalBytesRcvd = 0;
        printf("Received: ");                /* Setup to print the echoed string */
        while (totalBytesRcvd < echoStringLen)
        {
            /* Receive up to the buffer size (minus 1 to leave space for 
               a null terminator) bytes from the sender */
            if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
                DieWithError("recv() failed or connection closed prematurely");
            totalBytesRcvd += bytesRcvd;   /* Keep tally of total bytes */
            echoBuffer[bytesRcvd] = '\0';  /* Add \0 so printf knows where to stop */
            printf("%s", echoBuffer);            /* Print the echo buffer */
        }
    	
    
    
        printf("\n");    /* Print a final linefeed */
    
        closesocket(sock);
        WSACleanup();  /* Cleanup Winsock */
    
        exit(0);
    }
    select return 0 (timeout)
    Last edited by Russian; 02-08-2010 at 12:26 PM.

  2. #2
    Registered User
    Join Date
    Feb 2010
    Posts
    4
    problem solved. Moderators can delete the topic

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Rather than delete it, how about you explain your solution for the benefit of others?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Feb 2010
    Posts
    4
    implementation of the task (async recv and other) i will perform "off one's own bat"
    (Google Translate )
    Code:
    #include <stdio.h>      /* for printf(), fprintf() */
    #include <winsock2.h>    /* for socket(),... */
    #include <stdlib.h>     /* for exit() */
    #include <time.h>
    #include <sys/types.h>
    
    #define RCVBUFSIZE 3200   /* Size of receive buffer */
    
    void DieWithError(char *errorMessage){
        perror(errorMessage);
        exit(0);
    };  /* Error handling function */
    
    void main(int argc, char *argv[])
    {
        int sock, rc;                        /* Socket descriptor */
        struct sockaddr_in echoServAddr; /* Echo server address */
        unsigned short echoServPort;     /* Echo server port */
        //char *servIP;                    /* Server IP address (dotted quad) */
        char servIP[] = "10.42.43.1";
        char echoString[]= "identifier=1z2y3z \r\n\r\n";
        char echoBuffer[RCVBUFSIZE];     /* Buffer for echo string */
        int echoStringLen;               /* Length of string to echo */
        int bytesRcvd, totalBytesRcvd;   /* Bytes read in single recv() and total bytes read */
        WSADATA wsaData;                 /* Structure for WinSock setup communication */
        unsigned long nonblocking = 1;
        fd_set writefds, readfds;
        struct timeval tv;
        tv.tv_sec = 5;
        tv.tv_usec = 500000;
        //servIP =  argv[1];             /* First arg: server IP address (dotted quad) */
        echoServPort = 80; //atoi(8088);  //atoi(argv[2]);  /* Use given port, if any */
    
        if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) /* Load Winsock 2.0 DLL */
        {
            fprintf(stderr, "WSAStartup() failed");
            exit(1);
        }
    
        /* Create a reliable, stream socket using TCP */
        if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ) < 0)
            DieWithError("socket() failed");
       
    
        /* Set the socket to nonblocking */
        if (ioctlsocket(sock, FIONBIO, &nonblocking) != 0)
            DieWithError("ioctlsocket() failed");
    
        /* Construct the server address structure */
        memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
        echoServAddr.sin_family      = AF_INET;             /* Internet address family */
        echoServAddr.sin_addr.s_addr = inet_addr(servIP);   /* Server IP address */
        echoServAddr.sin_port        = htons(echoServPort); /* Server port */
    
        connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)); 
    
        FD_ZERO(&writefds);
        FD_SET(sock, &writefds);
        rc = select(sock, NULL, &writefds, NULL, &tv);
    
        if((rc == 1) && (FD_ISSET(sock, &writefds))) {
            printf("connect success\n");
        } else {
            printf("connect error\n");
        return;
        }
    
        send(sock, "1234", 4, 0);// send something
    
        FD_ZERO(&readfds);
        FD_SET(sock, &readfds);
        rc = select(sock, &readfds, NULL, NULL, &tv);
    
        printf("read\n");
    
    
        if((rc == 1) && (FD_ISSET(sock, &readfds))) { // get the answer and display
            bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0);
            printf("received %d bytes\n", bytesRcvd);
            printf("%s\n", echoBuffer);
            } else {
        printf("read error\n");
        return; 
        }
    
        WSACleanup();  // Cleanup Winsock
    }
    Last edited by Russian; 02-09-2010 at 03:46 AM.

  5. #5
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Ah yes Google Translations; providing translation humor for a generation...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > printf("%s\n", echoBuffer);
    Just "off the bat" as it were, where is the \0 at the end of this array you've recv()'ed ?

    Because recv() didn't store one, and neither did you.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by Salem View Post
    > printf("%s\n", echoBuffer);
    Just "off the bat" as it were, where is the \0 at the end of this array you've recv()'ed ?

    Because recv() didn't store one, and neither did you.
    Thats why I reset the buffer between runs with a memset()....
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    I prefer (after error checking) to do

    Code:
    bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0);
    echoBuffer[bytesRcvd] = '\0';
    It's considerably quicker than memset'ing.

    Using memset to clear any char array just seems like voodoo programming to me.
    Unless there is a nice comment like "cleared to prevent information leaks" or some other good reason.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by Salem View Post
    I prefer (after error checking) to do

    Code:
    bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0);
    echoBuffer[bytesRcvd] = '\0';
    It's considerably quicker than memset'ing.

    Using memset to clear any char array just seems like voodoo programming to me.
    Unless there is a nice comment like "cleared to prevent information leaks" or some other good reason.
    Not really. There are any number of C lib string methods that will fill a string with some formatted data and not stick on a terminating null. Seek them out to see what I mean...

    Here is but one...and the first one is always free

    strncpy - C++ Reference

    So if that is voodoo programming, well then BOOGA BOOGA! My code works.
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  10. #10
    Registered User
    Join Date
    Feb 2010
    Posts
    4
    Quote Originally Posted by Salem View Post
    I prefer (after error checking) to do

    Code:
    bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0);
    echoBuffer[bytesRcvd] = '\0';
    It's considerably quicker than memset'ing.
    in last version of my small socket-based client im using it
    you can see last ver at nonblocking sockets C at sources.ru

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > if ( ( bytesRcvd = recv( sock, echoBuffer, MAXDATASIZE, 0 ) ) == SOCKET_ERROR )
    So what happens if you make MAXDATASIZE larger than RCVBUFSIZE without realising the implications?

    In other words, try
    if ( ( bytesRcvd = recv( sock, echoBuffer, sizeof(echoBuffer)-1, 0 ) ) == SOCKET_ERROR )

    You also need to check for bytesRcvd == 0 as well.


    @jeff
    > There are any number of C lib string methods that will fill a string with some formatted data and not stick on a terminating null
    Fine, does this have a \0?
    Code:
    char buff[5];
    memset( buff, 0, sizeof(buff) );
    strncpy( buff, anotherstring, sizeof(buff) );
    ?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by Salem View Post
    > if ( ( bytesRcvd = recv( sock, echoBuffer, MAXDATASIZE, 0 ) ) == SOCKET_ERROR )
    So what happens if you make MAXDATASIZE larger than RCVBUFSIZE without realising the implications?

    In other words, try
    if ( ( bytesRcvd = recv( sock, echoBuffer, sizeof(echoBuffer)-1, 0 ) ) == SOCKET_ERROR )

    You also need to check for bytesRcvd == 0 as well.


    @jeff
    > There are any number of C lib string methods that will fill a string with some formatted data and not stick on a terminating null
    Fine, does this have a \0?
    Code:
    char buff[5];
    memset( buff, 0, sizeof(buff) );
    strncpy( buff, anotherstring, sizeof(buff) );
    ?
    At first glance that would depend on the size of anotherString.

    But who the hell codes that way? looks like one of those "sample" code pieces you used to see in the commercial lint tool in Dr. Dobbs...you know you always strncpy to 1 byte less than the size of your buffer...the memset was not a cure-all but to be taken together with common sense and experience.
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Unix Nonblocking Reads on Sockets
    By winderjj in forum Networking/Device Communication
    Replies: 5
    Last Post: 09-10-2008, 07:17 AM
  2. Best way to poll sockets?
    By 39ster in forum Networking/Device Communication
    Replies: 3
    Last Post: 07-22-2008, 01:43 PM
  3. nonblocking sockets - select approach
    By l2u in forum Networking/Device Communication
    Replies: 1
    Last Post: 09-26-2006, 11:43 AM
  4. Raw Sockets and SP2...
    By Devil Panther in forum Networking/Device Communication
    Replies: 11
    Last Post: 08-12-2005, 04:52 AM
  5. Starting window sockets
    By _Cl0wn_ in forum Windows Programming
    Replies: 2
    Last Post: 01-20-2003, 11:49 AM