My current project is a bare-metal webserver. For this I'm using no libraries, and programming directly onto the chip. What I'm trying to do right now is send a single piece of HTTP data:
HTTP/1.1 200 OK\r\n
Content-Length: 45\r\n
Content-Type: text/html\r\n
Server: microserver\r\n
Connection: close\r\n
\r\n
<!DOCTYPE html><html>Hello<br>world!<hr></html>
My server tries to go through the following steps:
Receive SYN
Send [SYN+ACK]
Receive ACK
Receive ACK containing HTTP GET
Send [ACK,PUSH,FIN] with HTTP data (this one changed a lot, I've tried sending ACK PUSH and FIN seperately (with the content in PUSH), tried [ACK+PUSH],FIN and ACK,[PUSH+FIN] as well.
Receive [ACK+FIN] <<--- Here's where it goes wrong, this one is never even sent, according to wireshark.
Send ACK.
As said, it goes wrong at step 6. every single time. No matter what combination of ACK, PUSH and FIN I use in step 5. When looking at it with wireshark all the SEQ and ACK numbers are correct.
My server is able to close connections once the [FIN+ACK] finally does get sent, which sometimes happens on sockets that are kept open by the browser synchronously.
Pcap file of what wireshark records: https://www.dropbox.com/s/062k9hkgkenaqij/httpdump.pcap with as filter: (tcp.dstport == 80 || tcp.srcport == 80) && (ip.dst == 169.254.100.100 || ip.src == 169.254.100.100)
I know there is a 4 year old very similar question, Building a webserver, client doesn't acknowledge HTTP 200 OK frame, but I've tried pretty much everything that was suggested in there, and it didn't seem to get me any further, so I'm out of ideas.
EDIT:
I have found the problem, after studying sections of wireshark captures for hours an end. Apparently the mistake was that I did not use data to calculate the TCP checksum... But well, found the solution.
Related
while(byte_count != 0){
byte_count = SSL_read(conn,get_buffer,sizeof(get_buffer));
printf("%s",get_buffer);
write_to_file(get_buffer,html,byte_count); // func to write to file
}
I've been trying to write a http/https client using sockets and SSL in C. The task is to get the HTML file of the landing page of a given website into a file on my system. I've handled the HTTP redirections and I was able to read only a portion of the HTTP payload since I've only called recv/SSL_read once. When I put this in a while loop it reads a few more 16kb segments and the connection times out. Is there any other way I can obtain whole of the HTML file ? (Sorry if this question seems vague, I'll be glad to make edits according to your responses)
everyone, i want to know when my tcp connection will be finished.
I mean the next: my prog is a client and it sends any messages to server, but it doesn't know when the server will close connection (send FIN flag).
Its look like handshake, prog send first msg, then receive and send next msg on the same socket, then serv send FIN - flag, thats mean end of tcp session or end of handshake as you like.
My target is to know when server say FIN, im using stream socket.
I tryed to use var flags from msdn doc int recv(SOCKET s ... int flags);. But now i think it isnt what im looking for...
int partresult = recv(*my_sock, RcvBytes, Size, 0);
(I'm assuming you're referring to TCP as the FIN is used only in that context).
A call to recv() will tell you what you're looking for: it will return 0 when a FIN was received (i.e. the remote socket output was shutdown) (already stated by #RemyLebeau, and -1 in case of error).
I'm using this answer as an opportunity to warn you about not comparing its return value with the number of bytes expected to read, as TCP does not guarantee a single send() can be read with a single read(). So do not test if (partresult < RcvBytes) ....
This question already has answers here:
When does an HTTP 1.0 server close the connection?
(1 answer)
Detect end of HTTP request body
(6 answers)
HTTP header line break style
(3 answers)
Closed 3 years ago.
I'm trying to create a server in C sockets that will allow file uploads through HTTP. The problem I'm having is that I get a very good chunk of the HTTP content but then it just stops sending and begins hanging, perhaps waiting for a response or something? But since recv never hits 0 it never gets to my response. (not sure thats even the reason why).
I looked around on google but most answers are about receiving data and looping to receive more when I'm already doing that.
Heres the code:
fp = fopen("fileName", "a");
for(;;)
{
ret = recv(fd, buffer, BUFSIZE, 0);
if(ret == 0){
\\ Never gets here unless I cancel the web request manually (pressing x where refresh usually is)
printf("Finished recieving");
char* sendHeader = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 8\n\nRecieved";
write(fd, sendHeader, strlen(sendHeader));
break;
}
if(ret == -1) {
printf("Error recieving");
break;
}
fprintf(fp, "%s", buffer);
}
fclose(fp);
Right now i'm just taking the file contents and appending it to a file.
The actual result's I'm getting is:
(using ... to abbreviate)
--WebKitFormBoundaryRMGRl...
Content-Dispotion: form-data; name="filetoUpload"; filename...;
Content-type: application/octet-stream
\n
Actual file contents
\n
--WebKitFormBoundaryRMGRl...
Content-Disposition: form data; name="submit"
Upload License
--WebKitFormBoundaryRMGRl...
Begins writing file contents again, writes about 10 lines, then hangs until I manually cancel request
When I print the byte values, i fill the buffer 2 times then the 3rd time it doesn't completely fill it and just hangs waiting?
Any ideas?
But since recv never hits 0 it never gets to my response ...
recv will return 0 if the client shuts down the connection. But the client will not shut down the connection since it want to receive the response (ok, it could shut down for writing then) and maybe wants to send more requests (HTTP persistent connection).
Instead you have to parse the HTTP request to figure out how much data the client will send in the body. The usual way to do this is by setting the Content-length header to the size of the body. If the size is not known up-front the client might use chunked transfer encoding though were each chunk is prefixed by its length (in hex).
Or in other words: if you are trying to implement HTTP then please make yourself familiar with the standard by studying it and not by making just assumptions. That's what standards are actually for.
I often find myself in need to test if an internet connection is online or not. In particular, sometimes it happens (on very, very peculiar connections) that UDP is disabled. Now, I figured that one of the most simple ways to test if UDP is available to my connection is through a DNS query.
Now, using some function like getaddrinfo abstracts away UDP from the query, so that (as far as my understanding goes) if UDP is not available, TCP will be used instead. Now, since I need to test for UDP connections, I will need to forge the UDP packet with the query myself. Moreover, I would like to make the query to a public DNS server (like 8.8.8.8), so that I am certain that the UDP connection is available to talk to external hosts.
So I am wondering: what is the most simple DNS query that I can send via an UDP packet? Could you show me an example that just asks for the ip, say, of google.com to a DNS server?
I'm not sure I understand your question fully, but the simplest query would be something like SOA for . (i.e. the start of authority for the root zone), like this:
$ dig SOA . #8.8.8.8
; <<>> DiG 9.8.3-P1 <<>> SOA . #8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46366
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;. IN SOA
;; ANSWER SECTION:
. 4350 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2015102500 1800 900 604800 86400
;; Query time: 36 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Oct 25 21:07:19 2015
;; MSG SIZE rcvd: 92
If you are asking what that looks like as a UDP packet, simply capture it with tcpdump. However, such trivial DNS packets are relatively easy to construct in C - see RFC1035. You may want to use a pre-existing library like c-ares or adns.
Note that as far as I remember, whether your resolver library falls back to TCP is implementation dependent. IIRC glibc on linux does not fall back to TCP, and libresolv on OpenBSD only does if /etc/resolv.conf contains options tcp. When using libresolv programatically you merely need to ensure RES_USEVC is clear.
If you are looking for example code, 'Stevens' TCP/IP illustrated' is the canonical answer.
I am using libcurl library to fetch abc-1.tar file from server. I want to know meaning of message which is display and process of execution of libcurl to display this messages.
For Example: I provide some messages below out of that I know basic message meaning like Content-Length means length of file which are downloaded, etc.
I want meaning of all messages, particularly messages which are start with * (e. g. Connection #0 to host (nil) left intact)
* Re-using existing connection! (#0) with host (nil)
* Connected to (nil) (182.72.67.14) port 65101 (#0)
GET /...... HTTP/1.1
Host: 182.72.67.14:65101
Accept: */*
Connection:keep-alive
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Length: 186368
< Content-Type: application/x-tar
< Server: Microsoft-IIS/7.5
< Content-Disposition: attachment; filename=abc-1.tar
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Tue, 01 Oct 2013 06:29:00 GMT
<
* Connection #0 to host (nil) left intact
cURL's Man Page specifies three types of "special" verbose output:
A line starting with '>' means "header data" sent by curl, '<' means "header data" received by curl that is hidden in normal cases, and a line starting with '*' means additional info provided by curl.
You can read about HTTP header fields in the HTTP official publication page. Any other output lines displayed by cURL belong to the HTTP body carried by the corresponding message.
So what is the actual meaning of these informationals starting with *, you ask? They inform you about the status of the transfer's TCP connection with the host. For instance:
"Connected to (nil) (182.72.67.14) port 65101 (#0)" means that a TCP connection is established with the server side (in your case: 182.72.67.14). The #0 is the TCP session number (which is used only by cURL). The nil indicates that the host name couldn't be resolved via DNS (had it been resolved, the it would've appeared instead of nil).
"Connection #0 to host (nil) left intact" means that although the transfer is over, the TCP session itself is still open (i.e no FIN/ACK exchanges have been made), allowing you to keep reusing the same TCP connection for multiple transfers (which could be useful if you don't want to sacrifice time on opening a new TCP connection).
The message "Re-using existing connection! (#0) with host (nil)" supports that, indicating that cURL does indeed that, riding an existing TCP connection (from a previous transfer).
Marked by < are HTTP headers.You can read in detail about http headers and their meaning here
and marked by * are verbose information provided by curl which is displayed on stderr.