?
Solved

Socket recv doesn't receive anything

Posted on 2009-12-23
11
Medium Priority
?
839 Views
Last Modified: 2012-05-08
Hi

I have coded a socket client which sends some data to web server (apache and PHP).

It works fine if I don't use recv. If I don't wait for response of server and simply after sending all data close the socket, I see received data in PHP and it works properly. But now I need to check server's response, so I need to do recv.

I tried to set socket option with SO_RCVTIMEO also. I don't receive anything at all!

I can't receive anything from server. If I don't set SO_RCVTIMEO, my program waits on recv forever. If I set the SO_RCVTIMEO I get in numbytes = -1

Please advice! I'm sure PHP replies with some data AT LEAST HTTP header. How I can solve it?

Even if it's possible to solved using PHP code I would do it. I already added exit() call in PHP code, so I think it will close connection. But it doesn't work.


I tried Connection: Close and Connection: Keep-Alive, NONE worked.

Please advice
0
Comment
Question by:CSecurity
  • 6
  • 5
11 Comments
 
LVL 53

Expert Comment

by:Infinity08
ID: 26111692
Could you show the C++ client code ?
Could you also show the PHP code on the other end ?
0
 
LVL 17

Author Comment

by:CSecurity
ID: 26111713
if ((h=gethostbyname2(THESERVER.c_str())) == NULL) return FALSE;
if ((sock = socket2(AF_INET, SOCK_STREAM, 0)) == -1) return FALSE;
    int iVal=0;

    unsigned int  sz = sizeof(iVal);
      iVal = 6000;
      int ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&iVal, sz);

if (connect(sock, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) return FALSE;

send(sock, slast, 49, 0);

numbytes=recv(sock, bufrec, DATASIZE-1, 0);    <-- Here it hangs! If I set timeout, I get out of hang but without ANY data!

DATASIZE is also defined as 100
#define DATASIZE 100



After timeout I get -1 in numbytes. If I don't set timeout with setsockopt I wait for ever!



PHP part does nothing and works well if I don't do recv and directly close socket with closesocket(sock);

but if I hang on recv PHP won't work also. I should close socket with closesocket(sock); then PHP works and receives what I send.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 26111911
I assume that socket2 is just an alias for socket.

SO_RCVTIMEO is not supported on all systems (only more recent systems support it), but I assume it is on yours.
Either way, if you use it on Linux, you need to pass a struct timeval as argument for setsockopt, not an int :

        struct timeval timeout = { 0 };
        timeout.tv_sec = 6;
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));

If you use it on Windows, it is indeed an int parameter. And you can use it like you did.

Make sure that a 6 second timeout is sufficient (it should be, but depends on the connection between client and server, as well as the load on the server).

I assume their_addr is set correctly, since the connection succeeds. But in any case, here's an example of what you should have :

        struct addrinfo hints;
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;

        struct addrinfo *their_addrinfo = 0;
        getaddrinfo(THESERVER.c_str(), "80", &hints, &their_addrinfo);

        int sock = socket(their_addrinfo->ai_family, their_addrinfo->ai_socktype, their_addrinfo->ai_protocol);

        connect(sock, their_addrinfo->ai_addr, their_addrinfo->ai_addrlen);

of course you'll need to add error handling everywhere.


Once the connection has succeeded, you can send and recv as the protocol dictates. For standard HTTP, you send the request, and receive the response. Then you usually end the connection (assuming keep-alive is not specified).

BUT, you need to specify the right sizes when you do. I assume you're sending 49 bytes because that is what you specified. Double-check that that is indeed the amount of data you send.
For recv, you don't know how much data you need to receive of course, so you specify a maximum. You specified 100. Make sure that the response is smaller than 100, or you won't receive everything.

Then we get to the error you experience. You say that recv returns -1. In that case, simply check what errno is set to to know what the exact error was that occurred.


>> PHP part does nothing and works well if I don't do recv and directly close socket with closesocket(sock);

Are you sure that the PHP part actually sends back a response ? You can use a network sniffer to see what is actually sent over the network. Use it on both ends to see which packets are sent/received on both ends. That will give you an accurate picture of what's happening.


You can also try your client code with another web server, like www.google.com eg. to see if it works as it should.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 17

Author Comment

by:CSecurity
ID: 26113362
I fixed the problem, solution is:

shutdown(socket, SD_SEND);

It closes sender socket and then I got received some data using recv. That's all
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 26113741
This indicates that there's something else going on. It shouldn't be necessary to shut down all sending operations just to be able to receive something.

I would recommend you check everything I pointed out in my previous post, because right now you've just hidden the bug, rather than solved it.
0
 
LVL 17

Author Comment

by:CSecurity
ID: 26116905
All things you worried about was correct, like socket2 is socket, size of data is 49, 6 second is enough as I was testing it with local apache server, etc.

I think we need to flush socket to apache, so apache starts processing. Flushing and ending sent packet occurs when you close send socket. Nothing to worry, I think. What do you think?
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 2000 total points
ID: 26118181
>> All things you worried about was correct

Those weren't things I was worrying about - I merely stated them for completeness, but was relatively confident that they were ok (otherwise a simple send would not even work).

What you don't seem to have tried are these suggestions I made :

1) did you try the code I posted ?
2) did you check what errno was set to when recv returns -1 ?
3) did you use a network sniffer (like Wireshark eg. : http://www.wireshark.org/) to check what is actually being sent over the network ? That will immediately uncover the problem.


>> I think we need to flush socket to apache, so apache starts processing.

As I said : if you need to do that, then there's another (possibly more serious) problem. So yes :

>> Nothing to worry, I think. What do you think?

I think there's something to worry about.
0
 
LVL 17

Author Comment

by:CSecurity
ID: 26118222
Got it working... Don't worry! I also had another problem which was adding \r\n in end of HTTP request twice
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 26118250
>> I also had another problem which was adding \r\n in end of HTTP request twice

That's not another problem. That's probably one of the reasons you saw the behavior you did. An extra \r\n could mean that the size was wrong and/or that the receiving end is waiting for more data before continuing.

Even if your problem is solved now, I do recommend to use a network sniffer to double check that all packets sent over the network now are actually how you expect them to be.
0
 
LVL 17

Author Comment

by:CSecurity
ID: 26118256
I checked with sniffer which caused to find source of problems! Now everything works like a charm! :) Thanks
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 26118276
>> I checked with sniffer which caused to find source of problems! Now everything works like a charm! :)

Great :) A sniffer is a great tool ! It's almost always the first thing I use to verify/analyse network behavior/issues.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question