I am currently working on a simple app to make my life easier. I made an android app which lets me pick a file and uploads it to a server. I am working on a windows PC c# app that sends its ip (dynamic) and its open port to my server.
Whenever the server receives a file from my phone, I want it to send a POST request to my PC.
I am fairly new to web stuff (I have done tons of coding before though), but as far as I understand only a server can receive a POST request.
How can I make a C# server that runs on my PC with a dynamic IP and receives POST requests?
I have been struggling with this for a while now, just simple keywords I should research would be very helpful, thanks.
HTTP is a protocol which lets Web Servers and Clients communicate. It requires you to have a web server (IIS, Apache or other) to respond to client http requests.
Client can send a GET, POST and others request type messages.
The prefable way is to send a web client using a WebClient class. Here is a sample taken from another answer given by Andrew
string URI = "site.com/mail.php";
using (WebClient client = new WebClient())
{
System.Collections.Specialized.NameValueCollection postData =
new System.Collections.Specialized.NameValueCollection()
{
{ "to", emailTo },
{ "subject", currentSubject },
{ "body", currentBody }
};
string pagesource = Encoding.UTF8.GetString(client.UploadValues(URI, postData));
}
I would create some kind of server application using WebAPI, SignalIR, WCF or ASMX web services. All of these can handle server/client communication and would make it easy to communicate with your device.
Related
I have an HTML application.
Some pages have to run websockets to connect to a server running an Asp.Net application and send/receive some messages through Websocket.
The websockets server works fine. But anyone can send some requests to the server. I would like my server to be protected and receives only authenticated requests. For example from Javascript in Developer Mode, I can run requests against Websocket server...
So far I'm accepting requests only from my domain as follows but that is not enough :
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
};
webSocketOptions.AllowedOrigins.Add("https://example.com");
webSocketOptions.AllowedOrigins.Add("https://www.example.com");
app.UseWebSockets(webSocketOptions);
Is there any way to authenticate Websocket requests ? Or for example allow only legitimate users send requests to the WS server ?
Thanks.
I hope someone else could provide more information - as I am not very familiar with WS(Web Sockets), but here what I would do (number 3 is probably what you want):
Validate Before WS connection is established - Self explanatory, don't create a WS connection if they had not authenticated via another method, but that's not always the option;
Use a specified format with a validation built it - Lets say the socket is expecting a message in the form of:
{
"Token": "27e0127341dfaojo",
"Message": "Hello World!",
"Command": "SendMessage"
}
If it is not in that format, then ignore it - and once it is, you can validate the token.
Using (Cookie Authentication) - the link explains more.
At start thank you all for your kind help! Every hint is great and can teach me a lot, I appreciate every comment! Before you respond I'm aware that there is a lot of working solutions and working ftp proxies, but I'm asking this question for learning purposes and I try to understand how it works.
I have to implement my own ftp proxy server to capture ftp commands. The issue is that request incoming to proxy from client is over http protocol and when I return raw ftp response from ftp server through proxy to the client, then client browser is not able to handle this response as ftp response. Currently I'm trying to hardcode initial response from ftp proxy as following:
var clientWriter = new BinaryWriter(clientNetStream);
clientWriter.Write("220 (vsFTPd 3.0.3)\r\n");
But when client browser got this response, then it is showing following box:
https://imgur.com/XcIy7Rw
Because above does not work then I've tried to include ftp response in HttpResponse as follows:
var clientWriter = new BinaryWriter(clientNetStream);
clientWriter.Write(
"HTTP/1.1 200 OK\r\n" +
"Date: Mon, 19 Jul 2004 16:18:20 GMT\r\n" +
"Server: Apache\r\n" +
"Last-Modified: Sat, 10 Jul 2004 17:29:19 GMT\r\n" +
"Accept-Ranges: bytes\r\n" +
"Content-Length: 9328\r\n" +
"Connection: keep-alive\r\n" +
"Content-Type: text/html\r\n" +
"\r\n" +
"220 (vsFTPd 3.0.3))\r\n");
But then browser handle this as follows:
https://imgur.com/JuFTjs7
What I try do to is return "220 (vsFTPd 3.0.3)\r\n" response from server to the client and then I expect that client will send "USER anonymous\r\n" command to log in, but with both solutions this is not happening. I try to make working following sequence automatically (please see Wireshark screenshot). https://imgur.com/yT3dRxW
Does anybody knows how to return response from server to the client, to make client to communicate with ftp server?
If client send http request to the proxy then can I return Ftp response instead of http response? If not, then how proxy response should looks like?
It is important to distinguish between a HTTP Proxy and a FTP proxy.
A HTTP proxy is typically capably to handle URLs starting with http(s):// and ftp://.
For URLs starting with ftp://, the proxy does a protocol transformation.
That means that the client uses the HTTP protocol to transmit the URL to the proxy (in this case starting with ftp://). Due to the URL starts with ftp://, the proxy knows that it must use the FTP protocol to connect to the server. This is referred to as FTP over HTTP as the client is connecting to a FTP server using a HTTP client.
Alternatively, the client can use a native FTP client to connect to the server using the proxy. In this case, the client uses the FTP protocol to talk to the proxy and the proxy uses the FTP protocol to talk to the server. This is referred to as native FTP proxy.
As you already noticed, in the FTPoverHTTP scenario, the client does not follow up on any FTP response. Instead, you have to implement the protocol transformation in the proxy accordingly. Pass the username and password from client to proxy as follows: ftp://username:password#server.com. Your proxy must extract the credentials from the URL, connect to the server, and then issue the USER and PASS command on behalf of the client.
Hint: The proxy also needs to extract directory/filenames from the URL in order to get a directory listing / file content using the FTP protocol from the server, then present it to the client accordingly, e.g. directory listing as html page with links to the artifacts in the directory or in case a file has been accessed, send a response which triggers a HTTP file download on the client
I've connected my bot application to the direct line API which is published with Azure. I am currently testing the application with a command line client application, the bot framework emulator, and the dev.botframework.com homepage for my bot.
Everything works correctly until I attempt to submit a GET request to a REST API. I've tested the GET API request in a separate project and it works correctly and the GET request worked prior to implementing the direct line channel. Is there anything I need to be aware of when making http requests with the direct line on the bot side?
Code in question
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", headerParam);
var response = client.GetAsync(new Uri("someUrl.com/api/v1/auth")).Result;
string content = response.Content.ReadAsStringAsync().Result;
var jo = JObject.Parse(content);
this.token = jo["Result"]["Token"].ToString();
}
await context.PostAsync(this.token);
the line that actually causes the failure is
var response = client.GetAsync(new Uri("someUrl.com/api/v1/auth")).Result;
Also is there an easier way to debug a project when it's published to azure and running direct line API?
System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: An attempt was made to access a socket in a way forbidden by its access permissions ipaddress
I have tried to invoke my custom REST API within my bot application back-end, then I could leverage Remote debugging web apps to retrieve the result from my bot application hosted on Azure web app as follows:
After searching for the related issue, I found that there be limitation for the number of sockets of your current app service plan when creating the new outgoing connections. You could try to scale up your App Service plan or create a new web app to isolate this issue. For more details, you could refer to this similar issue and this blog.
i just started with networking, learning how http worls and all that.
so my question is:
i have TcpClient connecting to an ip where website is located, but problem is that there is so many websites hosted on that server (goDaddy.com), I want to get contents of index.html,
of a website i want.
my code looks like that atm:
connector = new TcpClient("******", 80);
if(connector.Connected) Console.WriteLine("Connected\n");
so what kind of headers i need to send to apache so it gets the index.html for me,also would like to know the right way of sending it, without closing connection
Purpose for this:
-> I want to see headers that have been sent, and learn how to send my own headers.
big thanks in advance!
For HTTP data exchange it is simplier to use HttpClient, not TcpClient.
Try to read MSDN for HttpClient.
You can also use WebClient:
WebClient client = new WebClient();
string content = client.DownloadString("http://website.com/index.html");
TcpClient is a very low level object; it is not recommended to start with that one.
I am using a traditional C# web service client generated in VS2008 .Net 3.5, inheriting from SoapHttpClientProtocol. This is connecting to a remote web service written in Java.
All configuration is done in code during client initialization, and can be seen below:
ServicePointManager.Expect100Continue = false;
ServicePointManager.DefaultConnectionLimit = 10;
var client = new APIService
{
EnableDecompression = true,
Url = _url + "?guid=" + Guid.NewGuid(),
Credentials = new NetworkCredential(user, password, null),
PreAuthenticate = true,
Timeout = 5000 // 5 sec
};
It all works fine, but the time taken to execute the simplest method call is almost double the network ping time. Whereas a Java test client takes roughly the same as the network ping time:
C# client ~ 550ms
Java client ~ 340ms
Network ping ~ 300ms
After analyzing the TCP traffic for a session discovered the following:
Basically, the C# client sent TCP packets in the following sequence.
Client Send HTTP Headers in one packet.
Client Waits For TCP ACK from server.
Client Sends HTTP Body in one packet.
Client Waits For TCP ACK from server.
The Java client sent TCP packets in the following sequence.
Client Sends HTTP Headers in one packet.
Client Sends HTTP Body in one packet.
Client Revieves ACK for first packet.
Client Revieves ACK for second packet.
Client Revieves ACK for second packet.
Is there anyway to configure the C# web service client to send the header/body in parallel as the Java client appears to?
Any help or pointers much appreciated.
Thanks for the reply Rob, eventually I opted to use the Add Service Reference / WCF proxy generation, which does this by default. Probably because it's using newer HTTP libraries underneath.
I did have a few WCF proxy generation issues with SOAP methods that return raw arrays of complex objects (i.e.: returning an object that contains an array of objects worked fine). To get round this you either have to wrap your arrays in objects, or switch the SOAP server config from RPC to DOCUMENT (which is what we did).
I think you can use the inherited EndGetRequestStream method to hack the SoapHttpClientProtocol. Save that to a buffer until the request has finished. Then make your own stream and push it all out at once.