I was looking to learn more about web servers and so I followed this tutorial on codeguru to build a sample one. However, whenever I run it and load the default page, I get the standard GET http request and then another socket connection is accepted and then a blank http request is shown. The console output is below:
Web Server now listening on port 7070, press ^C to stop...
Socket Type: Stream
Client Connected!
=================
Client IP: 127.0.0.1:56310
Message received: "GET / HTTP/1.1
Host: localhost:7070
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
"
Directory requested: /
File Requested: C:\_WebServer\default.html
No. of bytes sent: 103
Total Bytes: 191
No. of bytes sent: 191
Socket Type: Stream
Client Connected!
=================
Client IP: 127.0.0.1:56311
Message received: " "
Only GET is supported :(
What is this blank http request and why is there a second socket connection even though I only made one request from my browser? Is this a sort of keep-alive thing?
Edit: Could this maybe be a timeout thing?
Edit2:
I think a reason for this might be the following:
server socket receives 2 http requests when I send from chrome and receives one when I send from firefox
It seems like Chrome does a bit of a "placeholder" socket request to optimise later transfers. I get this behaviour in IE as well though, so maybe IE is now doing something similar.
That code has so many errors that I would not recommend anyone reading it. The most severe is that it expects everything to be sent and received with a single operation which is just true for the most trivial operations.
If you want to learn how to code a web server I suggest that you look at my code: https://github.com/jgauffin/Griffin.Framework/tree/master/src/Griffin.Framework/Griffin.Core/Net/Protocols/Http
It's released under the apache license and I've separated the HTTP protocol parsing from the network IO which hopefully makes it easier to understand than the article that you linked to.
Related
I currently am working on a new project which will contain of a client in JavaScript with socket.io and a server in C#.
However, I have no clue how to respond to the data sent when I connect my client to the server.
In my JavaScript I have:
var socket = io('http://127.0.0.1:30000');
And I have SocketTest open and a server started on port 30000. SocketTest will receive the following data:
GET /socket.io/?EIO=3&transport=polling&t=MDMuIkH HTTP/1.1
Host: 127.0.0.1:30000
Connection: keep-alive
Accept: */*
Origin: http://127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Referer: http://127.0.0.1:8080/
Accept-Encoding: gzip, deflate, br
Accept-Language: nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: SOME COOKIE DATA
What do I correctly send back to the client with this?
Take a look here: C# Server Socket Program
You have to do networkStream.Read and networkStream.Write and whatever you decide to write back, you just need to interpret correctly on the JavaScript side.However
I suggest you take a look at JSON and maybe the following site because you are doing things that have been done for you already. Posting URL-encoded key values with HttpClient
The server is connected to the Port 30000, so you need to reads data from NetworkStream , and also write to the NetworkStream .
I need to send a series of get/post requests for an application I'm making (a custom wrapper for an online chat). I completed the site login process and initial chat loading, by loosely simulating requests logged from Telerik Fiddler.
Now I'm having trouble with a different post request, that registers the user as online.
It's a connection to a socket.io server, but I know for a fact it's possible to do without a socket connection, because everything worked fine when I sent my requests with Fiddler's "composer" feature.
Here's the request I'm trying to simulate
POST http://events.********.com/socket.io/1/xhr-polling/vLaINOG3fKixnNs-oTWq?t=1498442322413 HTTP/1.1
Host: events.********.com
Connection: keep-alive
Content-Length: 144
Origin: http://www.********.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Content-type: text/plain;charset=UTF-8
Accept: */*
Referer: http://www.********.com/home.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
5:::{"name":"updateUserStatus","args":[{"status":"online"}]}
Here's how it looks trying to simulate it (ignore the different url, it should work with this)
POST http://events.********.com/socket.io/1/xhr-polling/owR02QZlrwKOwcLjoTW8 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: events.********.com
Content-Length: 60
Expect: 100-continue
5:::{"name":"updateUserStatus","args":[{"status":"online"}]}
Clearly a lot of stuff missing, but I don't think most of it matters. What I've noticed is that the original request's header has content-type set to "text/plain," and even though I've tried many ways to change the accept and content-type headers to match, it always sends as application/json and results in a 404.image
I feel like I'm missing something really obvious and stupid, but I've been troubleshooting for the past couple hours and can't figure anything out.
Here's the code I'm using for the request (I took out the "text/plain" content-type and other stuff i had before that didnt work so it's somewhat cleaner)
chatreq = (HttpWebRequest)WebRequest.Create("http://events.********.com/socket.io/1/xhr-polling/" + socket);
chatreq.CookieContainer = cookieContainer;
postData = "5:::{\"name\":\"updateUserStatus\",\"args\":[{\"status\":\"online\"}]}";
data = Encoding.ASCII.GetBytes(postData);
chatreq.Method = "POST";
chatreq.ContentType = "application/x-www-form-urlencoded";
chatreq.ContentLength = data.Length;
using (var stream = chatreq.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
response = (HttpWebResponse)chatreq.GetResponse();
Or, if there's a simple way to send a raw http request, that would be great.
Thanks.
I used Headers.Clear() first, and then set all the headers, and it went through normally.
I ended up using a socket.io library for this project though, since it ended up being a lot easier.
I am using Silverlight 5, .NET 4.5.1 and OpenRIA.
A silverlight client calls a long-run OpenRIA operation. The operation is asynchronous. From the client side I can see that the function from a code is being called just once. From the IIS server-side on the other hand, the WCF function is called multiple times.
What I have logged through Fiddler - the operation was finished with an error. It was invoked once, but with a message „NOTE: This request was retried after a Receive operation failed.”
Request:
GET http://localhost:11213/ClientBin/KEEP-Web-Services-PayrollListService.svc/binary/GetPayrollList?payrollListId=efb1df5d-993a-4c4b-9fe6-013561547632 HTTP/1.1
Accept: */*
Referer: http://localhost:11213/ClientBin/KEEP.xap
Accept-Language: pl
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:11213
DNT: 1
Connection: Keep-Alive
Cookie: .KEEP_ASPXAUTH_iPersonel=8673CF25C5650AE86CE77A22B9C9A9D20E7588A077E5EADFFE8F5090F08B48639C9F309B1720BC4AD0D4DE342F149D52234DD8C5F15C0B0CCAD5A074C91E8F14B74FC27D7740A91614DECE034A9F99186375ACEB887E610B32CEA5786BF5EA02D35F144BC49D1E4C254478385EEB4D7E8811959E5494D9D6E9F17D698FCBDC93
Response:
HTTP/1.1 504 Fiddler - Receive Failure
Date: Wed, 28 Oct 2015 13:06:41 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Cache-Control: no-cache, must-revalidate
Timestamp: 14:06:41.238
[Fiddler] ReadResponse() failed: The server did not return a complete response for this request. Server returned 0 bytes.
The situation occurs in IISExpres and IIS 7.5, locally and remotely.
UPDATE 1.
I have found the reason that causes an operation repeated.
Failed to allocate a managed memory buffer of 134217728 bytes. The
amount of available memory may be low.
What I can do to handle it with OpenRIA (former wcf-ria-services)? I see no custom binding to have any effect to OpenRIA.
The problem was IIS in 32-bit. Using 64-bit version solves the problem.
P.S. Visual Studio has an option to use IIS-Express in 64-bit. You can also add to the registry:
reg add HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\WebProjects /v Use64BitIISExpress /t REG_DWORD /d 1
12.0 - Visual Studio 2013
I have a windows application which listens on 9002 port via system.net.socket.
If clients send the request over http url like that:
http://localhost:9002/projectName/doSomething
then in my ReceiveCallBack method the received data is:
POST /projectName/doSomething HTTP/ 1.1
Accept: * / *
Origin: http://localhost
Accept-Language: tr-TR
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko
Host: localhost:9002
But if they send the request over https url which you can see below:
https://localhost:9002/projectName/doSomething
then the received data is something like:
\0?\0\0?U:vv?W?????????T??k#?=??? v\tci\0\0,?(?'??\0=\0<\05\
I tried to use UTF8 encoding to convert this data in a readable format and searched over the Internet but I could not find the solution.
What is the way of receiving a readable data over HTTPS requests?
Thanks
I've actually written a web server and SOAP stack in C# from sockets up without using any WCF or HttpListener and had to deal with adding https support. The code was actually relatively simple.
You'll need to start by constructing a SslStream from the Socket, by way of a NetworkStream adapter.
var sslStream = new SslStream(new NetworkStream(socket));
Then the hard part: you need to AuthenticateAsServer, which requires you to have an X509Certificate with corresponding private key, from an issuer the connecting client trusts, containing a subject name matching the host portion of the https URL. (It's the hard part because you can't code your way out of it unless you own both sides of the connection - it's how a client such as a browser knows if a site is legitimate or not.)
sslStream.AuthenticateAsServer(serverCertificate);
Finally, you can then read from the sslStream and get the actual, unencrypted HTTP request.
You are probably seeing the first round of the handshake protocol for https. In https the two computers go through a multi-step handshake to negotiate what encryption to use, exchange public keys, etc. Even if you get through the handshake phase the data will be encrypted (which is kinda the point of using https).
I am currently developing a small websocket server in C# to handle connections from browsers.
I mostly used the code from Mozilla and Microsoft (respectively here and there). Unfortunately, when I try to connect to my basic server from a browser (the script was taken from websocket.org), the GET request appears to be fragmented...
I would like to understand why the GET request is divided into two parts. Let me show you my code and the output I get from it.
Code:
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = Encoding.UTF8.GetString(bytes,0,i);
Console.WriteLine("Received: {0}", data);
}
Output:
Received: GET / HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Received:
Sec-WebSocket-Version: 13
Origin: null
Sec-WebSocket-Key: 2QYy54zGPPKAkNyPgFjkbw==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
I also tried on Chrome to see how different it would be and by running the same code and the same script in the browser I get the following output:
Received: GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 127.0.0.1
Origin: null
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: mp5oLqe/YaQAxRksoVZWKg==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate; client_
Received: max_window_bits, x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
I see nothing wrong in the output with Chrome, so I don't really understand why the request is divided when using firefox...
I could merge the two parts of the request together, but if I understood the RFC6455 properly, any bad request should be dropped by the server.
Any suggestion?
Thank you very much.
That is totally fine. Maybe Firefox is sending the information in a way (slower) you have to read twice the network buffer but this is OK. It seems it is sending the common information that never change first, and after the information about the websocket (that has to be generated each time) last, probably to reduce the "time for the first byte".
Regarding to the HTTP protocol, the header ends when there is an empty line, so as long you do not get one and the network buffer contains information (readed!=0), you can continue reading the header.
Usually, you are going to find this situation often when doing network programming. You have to continue reading until the network stream says readed=0.