Using Webclient ontop of already created TCP Socket - c#

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.

Related

How to bind a specific port on a webclient object in C#

I am working on P2P application, I want to use the hole punching technique to connect peers.
here is my PHP third party Server Script.
<?php
echo "{yourIP:'".$_SERVER['REMOTE_ADDR']."',yourPort:".$_SERVER['REMOTE_PORT']."}";
?>
In my C# code I created a server socket which listens to 8765, when i want to get my public IP address and port number (in order to share with the peers), I send a request to php server using WebClient Object. The problem is the webclient object uses random local port to make request.
How to bind a webclient object to 8765 port? so that always the requests use this port as source port.
thanks!
Sorry for my poor english! :)
You will not be able to achieve this with WebClient, you can however solve it using HttpWebRequest:
public static IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
{
Console.WriteLine("BindIPEndpoint called");
return new IPEndPoint(IPAddress.Any,5000);
}
public static void Main()
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create("http://MyServer");
request.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(BindIPEndPointCallback);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}

C# Proxy Server: how to send/receive data with sockets?

I'm trying to create a simple proxy server in C#. Below is a portion of my code where I created a socket with the host name that was parsed from the browser HTTP request. The full request is in the string "header" and is sent to the destination socket. Then the while loop receives the response from the socket and sends it to the client socket.
Socket destServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
destServerSocket.Connect(host, 80);
destServerSocket.Send(ASCIIEncoding.ASCII.GetBytes(header));
byte[] response = new byte[1];
while (destServerSocket.Receive(response) != 0)
{
client.Send(response);
}
destServerSocket.Disconnect(false);
destServerSocket.Dispose();
client.Disconnect(false);
client.Dispose();
Right now my proxy only works with simple html sites. Anything else and it just endlessly loads without ever displaying any content in the browser. How do I alter my code to allow my proxy server to work on websites that are more complex than basic html ones?

HTTP over UDP adapter for Web API

I need to send some data from mobile clients to an ASP.NET ApiController. I cannot wait for an connection to be established (and I don't rely on the data to arrive), so I thought UDP is the way to go. On the server I need to listen on a UDP endpoint and redirect the request to my default HTTP endpoint.
This is what I have so far (shortened):
public class HttpOverUdpAdapter
{
public static UdpClient UpdListener;
public static void Start(int udpPort, tcpPort)
{
UpdListener = new UdpClient(udpPort);
new Thread(() =>
{
while (true)
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, udpPort);
byte[] bytes = UpdListener.Receive(ref endpoint);
TcpClient client = new TcpClient();
client.Connect(IPAddress.Loopback, tcpPort);
using (NetworkStream stream = client.GetStream())
{
stream.Write(bytes, 0, bytes.Length);
}
}
}).Start();
}
}
I get the following error when no matter what port I use:
System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.
Apart from that, is this going to work out at all? Is it correct to start it in Application_Start()?
Remark: WCF is no alternative.
There is no such thing as "I don't rely on the data to arrive" with HTTP. HTTP consists of requests and responses, which are usually big enough so that multiple IP packets are needed. UDP does neither guarantee the delivery nor the order of the packets, so you might end up with corrupt requests which might result in no response (which might be ok for you) or in a response for another web resource (which is probably not ok). Also, the response can be corrupt too in an unpredictable way (which is probably not ok for you).
If you would a need a more reliable transport you would add a reliability layer on top of the UDP tunnel, which is neither simpler nor faster than simply using TCP directly.

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.

how to send POST without waiting response 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
};

Categories