Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++C
Hi, I'm trying to play around a little with winsock, and I have this problem, where my recv() function doesn't seem to receive.
 
char buf[1000];
	do
	{
		gets(buf);
		if ((int)buf[0] == 0)
			send(mysock, "\r\n", 2, 0);
		else
			send(mysock, buf, strlen(buf), 0);
		
		recv(mysock, buf, sizeof(buf), 0);
		printf(buf);
 
	} while (strcmp(buf,"~") != 0);
 
I connect with this to google for example. After I send my request the recv() function gets my program stuck, and doesn't get the packet that was sent back to me from the server. What is the problem?
Posted 5-Sep-12 0:47am
DanDv242
Edited 5-Sep-12 3:04am
v2

1 solution

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

Solution 1

When connecting to a HTTP server (and I think you connected to one when saying Google) you must send valid requests to get an answer. This includes a trailing CR-LF pair (see RFC 2616[^]). The gets() function will remove the entered new line character. So the server receives your data but waits for the terminating CR-LF pair to process the request and answer.
 
But even when you add sending a CR-LF pair after your entered command, your code will probably fail. You are passing the length of the entered string as buffer size to your recv() call. You should read one of the many tutorials about Winsock to implement a receive function that handles received data of variable length.
 
You should also always check the return values of the send() and recv() calls.
  Permalink  
Comments
pasztorpisti at 5-Sep-12 8:51am
   
As far as I know gets() and its variants don't remove the newline characters but they convert between the system-dependent newline (CRLF) and C newlines (LF). If you read in with gets()/fgets() you will only see LF instead of CRLF. According to the standard HTTP servers have to handle only CRLF newlines but some of them work well with LF only newlines. In this example we send mixed newlines, both CRLF and LF, but a server that handles LF only characters might deal with this.
Jochen Arndt at 5-Sep-12 9:00am
   
I have checked it before posting (http://msdn.microsoft.com/en-us/library/2029ea5f.aspx): The gets function reads a line from the standard input stream stdin and stores it in buffer. The line consists of all characters up to and including the first newline character ('\n'). gets then replaces the newline character with a null character ('\0') before returning the line. In contrast, the fgets function retains the newline character.
pasztorpisti at 5-Sep-12 9:11am
   
Indeed. Then he can send a double newline so that part is OK.
DanDv at 5-Sep-12 9:09am
   
The send() is alright. I send the string "GET /" and after that "\r\n" and I do get a valid HTTP response. I sniffed the traffic to google using Wireshark and google sends me its home page. About the strlen(buf) on the recv() you are right, it was just a try and I forgot to change it back before I asked the question here. However it still doesn't work even if I write sizeof(buf). Can the buffer be bigger than the content-length? If so, how do I know the content-length of the response?
pasztorpisti at 5-Sep-12 9:13am
   
You should put the recv() outside after the loop. And yes, the received data can be easily bigger than your buffer, you should check the return values of send() and recv().
Jochen Arndt at 5-Sep-12 9:21am
   
Thank you for answering. Just the additional note to read the recv() documentation and the example code at http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121%28v=vs.85%29.aspx. The response contains the context length information. So the buffer must be large enough to receive this information and a new buffer can be then allocated to receive the complete response.
DanDv at 5-Sep-12 9:36am
   
Wow man, it worked. I don't understand why however, what does it have to do with the recv in or outside the loop?
Chuck O'Toole at 5-Sep-12 9:44am
   
How many times did you go through the "send" loop before it exited. Why would you expect a "recv" for each and every "send". HTTP protocol requires that you send a bunch of legal header stuff before the web site responds to you so until you are *done* sending, the web site will not respond so there's nothing to recv. That's why putting it outside the loop works, you completed sending the request, *then* you recv.
DanDv at 5-Sep-12 9:48am
   
Thanks man, now I get it. But what if I wanted just to receive the TCP packet with the ACK in it, for my headers and stuff, and not the HTTP response (Of course this isn't my intention, I'm just asking).
pasztorpisti at 5-Sep-12 9:59am
   
What do you mean on ACK??? Your ACK in HTTP is the response. You send something like this as a request: Request header CRLF header1: value1 CRLF header2: value2 CRLF headerx: valuex CRLF CRLF <-- This empty line indicates the end of the header of your request [optional content bytes, maybe with chunked transfer encoding] The you receive the response to this that has a similar structure as your request.
DanDv at 5-Sep-12 10:06am
   
I don't mean that. I mean that I wanna see the TCP packet that was sent back to me, before I even finished my request. In my program I'm sending the CRLF in another packet. For example at first I send("GET \"), and then I send("\r\n"). The server at first doesn't know I am about the send an HTTP request, but it sends me after my first send a TCP packet with the ACK flag. Only after my second send the server responses with a normal HTTP response. My question is how do I see the TCP packet?
pasztorpisti at 5-Sep-12 10:09am
   
With standard socket APIs you can't do that, and you don't want to do that because its totally pointless. What is your intention with that?
DanDv at 5-Sep-12 10:11am
   
As I said, I was just asking. Thanks for the answers.
Chuck O'Toole at 5-Sep-12 10:05am
   
ok, going from the specific "HTTP" to the generic "TCP Packets", when you are coding "send" and "recv", you are implementing your end of a "protocol", an agreement between you and the other program on what constitiutes a "message / command" and what constitutes a "reply / response". The number and sequences of "sends" has to match the other programs number and sequences of "recvs" and visa-versa, otherwize one of you has violated the protocol. In this instance, you are talking to an HTTP Server (WinInet, Apache, whatever) and the protocol they've implemented does *not* include sending you "acks".
DanDv at 5-Sep-12 10:11am
   
Okay, I got it, thanks.
Jochen Arndt at 5-Sep-12 9:28am
   
Just one more note: The buffer should be bigger than the response. Or call recv() from within a loop using the return value until all data has been retrieved. Otherwise you will receive remaining data with your next query.

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

  Print Answers RSS
Your Filters
Interested
Ignored
     
0 Shai Vashdi 339
1 Sergey Alexandrovich Kryukov 305
2 OriginalGriff 290
3 Peter Leow 171
4 Guruprasad.K.Basavaraju 170
0 Sergey Alexandrovich Kryukov 8,979
1 OriginalGriff 5,280
2 Peter Leow 4,010
3 Maciej Los 3,535
4 Abhinav S 3,263


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