Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
I have the code for client in which i am making the socket connection with server but the client socket waits until the server closes the socket and then client closes the socket BUT i want is, that client socket(recv call) should wait for 30second on the socket and if no data comes it should move forward,should not be a BLOCKING call
 
Code is as follows:-
 
int __cdecl main(int argc, char **argv) 
{
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
                    *ptr = NULL,
                    hints;
    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];
    int iResult;
    int recvbuflen = DEFAULT_BUFLEN;
    
    // Validate the parameters
    if (argc != 2) {
        printf("usage: %s server-name\n", argv[0]);
        return 1;
    }
 
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }
 
    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
 
    // Resolve the server address and port
    iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }
 
    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
 
        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
 
        // Connect to server.
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }
 
    freeaddrinfo(result);
 
    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }
 
    // Send an initial buffer
    iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
 
    printf("Bytes Sent: %ld\n", iResult);
 
    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
 
    // Receive until the peer closes the connection
    do {
 
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());
 
    } while( iResult > 0 );
 
    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();
 
    return 0;
}
Posted 11-Sep-12 21:00pm

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

The solution is switching the socket to non-blocking mode and then waiting for the socket with select() until the socket becomes readable. With select() you can setup a timeout and when select() returns you can check whether the reason was a timeout or success/failure. If it was success then read out some bytes from the socket. If the received bytes were not enough for example because you received just one byte then jump back to your select() call and wait again for the socket to become readable but this time you have to calculate the new timeout value from the read operation start time and the current time. (Don't rely on select() to return the elapsed time in its last parameter after a timeout, its platform dependent).
I have a blocking-socket C++ class for myself that has a non-blocking socket handle inside and its methods emulate blocking socket calls using select and every methods allow the use of a timeout/deadline. You can use this select trick for every socket operations. With non-bocking sockets don't forget to check for EWOULDBLOCK error code after operations that would otherwise block.
  Permalink  
v2
Comments
Tarun Batra at 12-Sep-12 4:21am
   
Thanks for the reply sir,can u share your class if u have no problem regarding sharing
pasztorpisti at 12-Sep-12 4:25am
   
Sorry, I've replied as if you wanted a timouted connect, now I corrected the solution to describe what you have to do in case of recv(). Unfortunately my code is not public domain but I've described how to do it step by step.
Tarun Batra at 12-Sep-12 4:30am
   
So according to your solution i have to use select() call after connect() call and before recv() call.Is there any Flag to set the socket in Non Blocking Mode?
 
pasztorpisti at 12-Sep-12 4:32am
   
Forget about the connect, I misinterpreted your question and described a non-blocking connect in my first solution. If you want a recv with timout then connect as you did before, switch the socket to nonblocking mode, and then perform your recv as I described then you can switch the socket back to blocking mode. Yes, you are using select to block until your socket has data to read out. If you perform a nonblocking recv call on the socket before it becomes readable then it returns with error and WSAGetLastError() returns EWOULDBLOCK. For this reason first you have to wait for the socket to receive some bytes from the network using the select() call, and you use the recv only after that.
pwasser at 12-Sep-12 4:32am
   
Suggest you read about ioctlsocket().
Tarun Batra at 12-Sep-12 4:35am
   
Will read ioctlsocket() thanks for the suggesstion
pasztorpisti at 12-Sep-12 4:36am
   
ioctlsocket() is needed only to switch the socket to non-blocking and switching back, read the example I posted, thats enough for now.
pasztorpisti at 12-Sep-12 4:35am
   
Here is an example to switch the socket to non-blocking: http://www.codeproject.com/Tips/168704/How-to-set-a-socket-connection-timeout
You switch back to blocking the same way by changing the parameter.
Tarun Batra at 12-Sep-12 6:08am
   
Really thanks for the link sir
pasztorpisti at 12-Sep-12 7:01am
   
You are welcome!
Tarun Batra at 12-Sep-12 7:55am
   
Sir can u help me one more thing
pasztorpisti at 12-Sep-12 8:01am
   
It depends. Question?
Tarun Batra at 12-Sep-12 8:06am
   
I have one pdf in which sending data to a dialysis machine is defined but not defined how to calculate check sum and a;so i am not getting any data from machine.Can u send em your mail id i will send the pdf to you
pasztorpisti at 12-Sep-12 8:59am
   
Sorry, but the answer is no.
Tarun Batra at 12-Sep-12 11:15am
   
please look at this http://www.codeproject.com/Questions/457990/Please-is-this-correct-formation
Tarun Batra at 14-Sep-12 13:54pm
   
sir please tell the solution of this http://www.codeproject.com/Questions/459502/Please-tell-how-to-make-event-level-socket-program
Tarun Batra at 12-Sep-12 6:08am
   
Really thanks for the link sir

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 280
1 Jochen Arndt 150
2 Kornfeld Eliyahu Peter 120
3 PIEBALDconsult 110
4 Richard MacCutchan 105
0 OriginalGriff 6,055
1 DamithSL 4,621
2 Maciej Los 4,087
3 Kornfeld Eliyahu Peter 3,500
4 Sergey Alexandrovich Kryukov 3,294


Advertise | Privacy | Mobile
Web02 | 2.8.141220.1 | Last Updated 12 Sep 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100