how to send POST without waiting response C# - c#

how to send POST without waiting response in C#?
How can I do it?
Help please!

Use one of the asynchronous methods in the WebClient class, for example UploadStringAsync.
The corresponding event (UploadStringCompleted for the example) will be triggered when the post is completed (or fails), but you don't have to hook up any handler for the event. You might want to do that, however, to check if there was any error.

An HTTP session is just a standard TCP session, and a POST is just a properly formatted piece of data that meets the HTTP specification. You can open a TCP connection to the web server and send a POST request and then close the TCP connection. You can check the HTTP specification (RFC 2616) to learn how to properly format a POST. You can find it at: http://www.w3.org/Protocols/rfc2616/rfc2616.html
A very basic POST would be sending the following over a TCP connection:
POST / HTTP/1.1
Host: www.thehost.com
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
Hi!
Substituting the content, and the corresponding length with whatever you want to send, changing the / to the correct path and putting the hostname or IP of the host at Host:... and connecting the TCP session to that host of course.
A very very basic example:
using System.Net;
using System.Net.Sockets;
static void Main(string[] args)
{
string Hostname = "www.website.com";
TcpClient Client = new TcpClient(Hostname, 80);
Client.Client.Send(new ASCIIEncoding().GetBytes("POST / HTTP/1.1\nHost: "+Hostname+"\nConnection: close\n\n"));
Client.Close();
}
Changing www.website.com to the correct hostname (and the port if required).

UploadValuesAsync looks like a more complete solution, using something like this:
using (var client = new WebClient())
{
var values = new NameValueCollection();
// add values...
client.UploadValuesAsync(new System.Uri(rawUrl), "POST", values);
}
However note that I haven't tested this code as I was trying to solve a slightly different problem.

var wc = new WebClient();
wc.Headers["Content-type"] = "application/x-www-form-urlencoded";
wc.UploadStringAsync(uri, data);
wc.UploadStringCompleted += (sender, e) =>
{
// completed
};

Related

Using Webclient ontop of already created TCP Socket

I need to communicate via a HTTP-Rest interface with a device.
I cannot create a connection to this device actively.
This device is creating a TCP-Socket with my program. So, I am listening on a port for this device.
After the Socket is created, I need to send HTTP-Requests to this device on top of that socket. I Am acting as HTTP-Client and the device is acting as HTTP-Server.
I cannot use WebClient for that as it creates its own TCP-Socket. But the socket as I said is already created.
My fist question would be: Is there still a way to use WebClient or another alternative to create the HTTP-Requests and read out the Responses?
If I cannot use Webclient I need to implement it by myself.
I saw that it is possible to use WebClient to create HTTP Header Bytes:
void SendHTTPRequest(string message)
{
//create Header Bytes
WebClient web = new WebClient();
web.Headers.Set(HttpRequestHeader.Connection, "keep-alive");
web.Headers.Set(HttpRequestHeader.Accept, "*/*");
web.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate, br");
//Built list with request bytes
List<byte> bytesToSend = new List<byte>();
bytesToSend.AddRange(Encoding.ASCII.GetBytes(message));
bytesToSend.AddRange(web.Headers.ToByteArray());
//Send request to the device
WriteBytes(bytesToSend.ToArray());
}
My Second Question would be: Is there a way to decode the HTTP-Headers out of the received bytes from the response? So that I only need to implement the write and read methods for the HTTP-Body.

Why does WebClient.UploadValues overwrites my html web page?

I'm familiar with Winform and WPF, but new to web developing. One day saw WebClient.UploadValues and decided to try it.
static void Main(string[] args)
{
using (var client = new WebClient())
{
var values = new NameValueCollection();
values["thing1"] = "hello";
values["thing2"] = "world";
//A single file that contains plain html
var response = client.UploadValues("D:\\page.html", values);
var responseString = Encoding.Default.GetString(response);
Console.WriteLine(responseString);
}
Console.ReadLine();
}
After run, nothing printed, and the html file content becomes like this:
thing1=hello&thing2=world
Could anyone explain it, thanks!
The UploadValues method is intended to be used with the HTTP protocol. This means that you need to host your html on a web server and make the request like that:
var response = client.UploadValues("http://some_server/page.html", values);
In this case the method will send the values to the server by using application/x-www-form-urlencoded encoding and it will return the response from the HTTP request.
I have never used the UploadValues with a local file and the documentation doesn't seem to mention anything about it. They only mention HTTP or FTP protocols. So I suppose that this is some side effect when using it with a local file -> it simply overwrites the contents of this file with the payload that is being sent.
You are using WebClient not as it was intended.
The purpose of WebClient.UploadValues is to upload the specified name/value collection to the resource identified by the specified URI.
But it should not be some local file on your disk, but instead it should be some web-service listening for requests and issuing responces.

Establishing a simple websocket handshake

Client:
<script type="text/javascript">
var socket = new WebSocket('ws://localhost:8183/websession');
socket.onopen = function () {
alert('handshake successfully established. May send data now...');
};
socket.onclose = function () {
alert('connection closed');
};
</script>
server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
class Program
{
static void Main(string[] args)
{
var listener = new TcpListener(IPAddress.Loopback, 8183);
listener.Start();
using (var client = listener.AcceptTcpClient())
using (var stream = client.GetStream())
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
writer.WriteLine("HTTP/1.1 101 Web Socket Protocol Handshake");
writer.WriteLine("Upgrade: WebSocket");
writer.WriteLine("Connection: Upgrade");
writer.WriteLine("WebSocket-Origin: http://localhost:8092");
writer.WriteLine("WebSocket-Location: ws://localhost:8183/websession");
writer.WriteLine("");
}
listener.Stop();
}
}
the problem is that the connection is never established and the onopen function is never called what may be the problem ?
Firstly, your "server" seems to be sending the "client" part of the handshake. Secondly, StreamReader and StreamWriter will not help you much; frankly, you would do well just to use the Stream.
Now, the actual handshake is complicated; both client and server need to prove to each-other than they are actually talking web-sockets, and not HTTP. The exact nature of this depends on the version of the protocol you are trying to support (or multiple protocols), but the server is required to perform a maths calculation based on the headers that the client sends; the server sends the answer back in its headers, and this checks that they are talking the same language. Note that this is not a security step: it is a sanity protection step. This is all described in the specification, but an example request / response pair is (from that document):
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
And:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
After which, it drops from HTTP into web-socket protocol, which is binary and unrelated to HTTP. For info, Sec-WebSocket-Accept is the result of the maths calculation, based on the client's Sec-WebSocket-Key.
The next bit of code that you will need is frame support. Again - see the specification. Also keep in mind that this specification is just version 13. If you want to support all clients, you might need to check the older specifications too (there are some subtle tweaks, except for the original original protocol, which was radically different and will require completely different code).
Before writing all this, you might want to look into whether a pre-existing library would be more practical. Windows 8 (and similar versions of server) include web-socket supprt direct in HTTP.SYS, with full support in .NET.

Resend HTTP header

I have application. It send request to my proxy class. Proxy must to parse http header string (I done this) and resend it request to server to get a video.
At first, mediacomponent connect to proxy:
var uri = new Uri("http://127.0.0.1:2233/files/1.mp4");
videoPlayer.Source = uri;
Play();
Proxy get http header string
"GET /files/1.mp4 HTTP/1.1\r\nCache-Control: no-cache\r\nConnection: Keep-Alive\r\nPragma: getIfoFileURI.dlna.org\r\nAccept: */*\r\nUser-Agent: NSPlayer/12.00.7601.17514 WMFSDK/12.00.7601.17514\r\nGetContentFeatures.DLNA.ORG: 1\r\nHost: 127.0.0.1:2233\r\n\r\n"
I replase host:
"GET /files/1.mp4 HTTP/1.1\r\nCache-Control: no-cache\r\nConnection: Keep-Alive\r\nPragma: getIfoFileURI.dlna.org\r\nAccept: */*\r\nUser-Agent: NSPlayer/12.00.7601.17514 WMFSDK/12.00.7601.17514\r\nGetContentFeatures.DLNA.ORG: 1\r\nHost: myserver.ru\r\n\r\n"
Now proxy must get video from server. What must I do?
When using .NET, you don't have to manually create the HTTP message itself. Instead, use the classes in the System.Net.Http namespace to form and send an HTTP message and process the response.
For example, sending an HTTP GET message to a URL can be as simple as:
var uri = new Uri("http://www.foobar.com/");
var client = new HttpClient();
string body = await client.GetStringAsync(uri);
Note that this general approach will download the entire contents of the resource at the given URI. In your case, you may not want to wait for the whole video to download before you start playing/processing/storing it. In which case, you might want to use the HttpClient.ReadAsStream() method which will return a stream from which you can read until the stream closes.

Pipelining using HttpWebRequest in C#

I am working on an HTTP client which should ideally pipeline requests when needed. Also, the requests will be sent on specific network interfaces (the client is multihomed).
Asynchronous sockets are used and in order to make a request, I use the following code:
Uri url = new Uri(reqUrl);
ServicePoint sp = ServicePointManager.FindServicePoint(url);
sp.BindIPEndPointDelegate = new BindIPEndPoint(localBind);
pseg.req = (HttpWebRequest)HttpWebRequest.Create(url);
pseg.req.AddRange("bytes", psegStart, psegStart + psegLength - 1);
pseg.req.KeepAlive = true;
pseg.req.Pipelined = true;
For each request made using this code, a separate connection to the server is opened and segments received in parallell. This is ok, however, it is not the behavior I want. I want the requests to be pipelined, but the replies to arrive sequentially. If I use locking or set the connectionlimit to 1, the request for segment #2 is not sent until after segment #1 has been fully received.
Is there any way to achieve what I want and still use the HttpWebRequest/Response-classes? Or will I have to drop down to sockets?

Categories