Cant connect Client-Server with Websockets - c#

Im create simple web server on C# .Net Framework with Tcp-Listner Tcp-Client connections.
Now im trying to do support of Websocket connection for chat\or something else.
For sockets im use GenericHandler and js for connect them. After getting request from client
GET /socket/SocketHandler.ashx HTTP/1.1
Host: ***************
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
Upgrade: websocket
Origin: http://************
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
Sec-WebSocket-Key: aroK0T3g3A6oSxC6Qz1QDg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
im sending response to client from server with concatenate key aroK0T3g3A6oSxC6Qz1QDg== with GUID, hash it SHA1 and convert in Base64 format for getting accept key zGccDw/PeOtlWAmdPT6HBtyywYc=
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: zGccDw/PeOtlWAmdPT6HBtyywYc=
Sec-WebSocket-Protocol: chat
but after this, client (browser) says
failed: Error during WebSocket handshake: Incorrect
'Sec-WebSocket-Accept' header value
So, what im do wrong and how to fix that?
upd: for example, im use this code for conversion
string ClientKey = socketKey;
string GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
var conc = ClientKey + GUID;
var buffer = Encoding.UTF8.GetBytes(conc);
var hash1 = SHA1.Create().ComputeHash(buffer);
var AcceptKey = System.Convert.ToBase64String(hash1);

I have also my own WebSocket client in C#. And It had been tested and working with ASP.NET Core.
Then, I've tested your secure key, the result is different. I got below hash.
QCd+628gwEVYxyYQ8ekJny8ZHCo=

Related

C# server respond to socket.io

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 .

How do I simulate this post request in C#

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.

Fragmented GET request when using websocket in Firefox

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.

How do i replicate a webrequest with custom parameters (not postdata, not url parameters)?

Context:
Hi everyone, i am trying to simulate a query on this website, but i am failing to do so.
I am using C# and a custom self developed library to Wrap the WebRequests actions making it easier to simulate Posts and Gets for Strings and Bitmaps.
Also, i'm using Fiddler2 Web Debugger to debug the web requests of the service
How to test the service Yourself:
Link to the service
Use this document on the first white box : 04034872000121
Write the captcha and click at "Consultar"
Thats it.
Problem:
After Debuging the requests with fiddler, and replicated everything on code (Cookies, Origin, Host, Postdata with a huge json and so on).
The request for the query, still not working, it redirects me to the home page again, instead of querying the document. (I am allowing "AutoRedirect" on web request object).
The only parameter that i'm not beeing able to replicate is the : GxAjaxRequest: 1
Here is the Fiddler debug feedback of the request:
POST http://sefaznet.ac.gov.br/sefazonline/servlet/hpfsincon?0898a16d81a4e94896958b17b52f252d,gx-no-cache=1354713117196 HTTP/1.1
Host: sefaznet.ac.gov.br
Connection: keep-alive
Content-Length: 1337
Origin: http://sefaznet.ac.gov.br
GxAjaxRequest: 1 **Weird Parameter. I've never saw it before.**
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11
Content-Type: application/x-www-form-urlencoded
Accept: */*
Referer: http://sefaznet.ac.gov.br/sefazonline/servlet/hpfsincon
Accept-Encoding: gzip,deflate,sdch
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: GX_SESSION_ID=vSLRLKed3eXJGMBorGepVtQkJOQ1I3o0EBUVzT0g%2BI8%3D; JSESSIONID=af2ba968b7889ec8869caaaba281
vNUMDOC=04034872000121&cfield=chin&BUTTON1=Consultar&BTN_VOLTAR=Retornar&GXState=%7B%22_EventName%22%3A%22E'VISUALIZADADOS'.%22%2C%22_EventGridId%22%3A44%2C%22_EventRowId%22%3Aundefined%2C%22nRC_Duplicados%22%3A%220%22%2C%22CAPTCHA1_Reloadimagetext%22%3A%22Obter%20nova%20imagem!%22%2C%22CAPTCHA1_Validationresult%22%3A1%2C%22GX_FocusControl%22%3A%22vNUMDOC%22%2C%22GX_AJAX_KEY%22%3A%2264FFFF0AFF7A4DFF2655FFFFFF26FF77%22%2C%22AJAX_SECURITY_TOKEN%22%3A%221a9634f566dcd40d12bb8146fd7ff6edca12ae737a3743d79b4b826c3bd4a604%22%2C%22GX_CMP_OBJS%22%3A%7B%7D%2C%22sCallerURL%22%3A%22%2Fsefazonline%2Fservlet%2Fhpfsindado%3FeTlFtl5mBgEOtpLCt8Q02bMjmN3K93hV7i2Uxq_rHv0%3D%22%2C%22GX_RES_PROVIDER%22%3A%22com.genexus.webpanels.GXResourceProvider%22%2C%22GX_THEME%22%3A%22GeneXusX%22%2C%22_MODE%22%3A%22%22%2C%22Mode%22%3A%22%22%2C%22IsModified%22%3A%221%22%2C%22MESSAGE_Width%22%3A%22100%22%2C%22MESSAGE_Height%22%3A%22100%22%2C%22MESSAGE_Show%22%3A%22false%22%2C%22MESSAGE_Title%22%3A%22Title%22%2C%22MESSAGE_Message%22%3A%22This%20is%20the%20message%22%2C%22MESSAGE_Type%22%3A%22alert%22%2C%22MESSAGE_Icon%22%3A%22info%22%2C%22MESSAGE_Cls%22%3A%22%22%2C%22MESSAGE_Position%22%3A%22t%22%2C%22MESSAGE_Duration%22%3A1%2C%22MESSAGE_Visible%22%3A1%2C%22CAPTCHA1_Width%22%3A%22140%22%2C%22CAPTCHA1_Height%22%3A%2239%22%2C%22CAPTCHA1_Visible%22%3A1%7D&
Question:
How do i actually replicate/add this parameter to my webrequest via code ?
Is there any way to do so ?
By the way, the site messes alot with scripts which was hard to "figure out" the origin from most parameters used on the requests.
I hope someone might help me out.
Thanks in advance.
I've figured out.
The problem was that i've had to add a custom header to each request.
webRequest.Headers.Add ("customheadertext and value");
Now fiddler shows correctly my new request, with the added header
POST http://sefaznet.ac.gov.br/sefazonline/servlet/hpfsincon?0898a16d81a4e94896958b17b52f252d,gx-no-cache=1354721123208 HTTP/1.1
GxAjaxRequest: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1
Content-Type: application/x-www-form-urlencoded
Referer: http://sefaznet.ac.gov.br/sefazonline/servlet/hpfsincon
Host: sefaznet.ac.gov.br
Cookie: GX_SESSION_ID=B8w8AQ4W%2FLzLHIpBor3JwJDQAWGy1xRqCYUMnzF14Yk%3D; JSESSIONID=c19564cbebfab1911442fd64a0bb
Content-Length: 1291
Expect: 100-continue
Accept-Encoding: gzip, deflate

Get endpoint IP from URL

Using a TCP Client for http post. I get a different result than excepted.
No HTTP 200 OK...
Here is my Request:
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: de-DE
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
Host:www.mywebsite.com
Connection: Keep-Alive
Cache-Control: max-age=0
Here is my Response:
HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Location: http://somewhere.com (url changed)
Content-Length: 0
Date: Fri, 03 Aug 2012 10:38:14 GMT
Its tell me to redirect to "Location".
The next request should be a GET to http://somewhere.com with a refer to www.mywebsite.com ?
A other scenario is a https link. Its often a total different IP than the HostEntry returns. How to get the IP ? Is there an easy way in c# ?
Yes a 302 means that the url is not at the location you want (the host may have moved it, or prefers you use www instead of the apex). So just use a HTTP GET for the new URL.
In terms of the IP Address, I'm afraid its not so simple, you can have multiple IP Addresses for a hostname
string stackoverflow= "stackoverflow.com"
IPAddress[] addresslist = Dns.GetHostAddresses(stackoverflow);
foreach (IPAddress theaddress in addresslist)
{
Console.WriteLine(theaddress.ToString());
}
There are lots of situations where more than one IP is used (mainly load balancing situations).

Categories