I have the following HTTP listener method, greatly inspired by MSDN's example use of the HttpListener class. I'm fairly new to programming and I'm not sure where to go from here to initialize it from my Main(). Any suggestions?
public static void HttpListener(string[] prefixes)
{
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("Prefixes needed");
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
Console.WriteLine("Listening..");
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
string responseString = "<HTML><BODY> Test </BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
listener.Stop();
}
You seem to have removed the comments that are mentioned on the MSDN HttpListener Class page:
// URI prefixes are required, for example "http://contoso.com:8080/index/".
So just call it like that:
public static void Main(string[] args)
{
HttpListener(new[] { "http://localhost/" });
}
But please note this example will handle only one request and then exit. If your follow-up question is then "How can I make it handle multiple requests?", see Handling multiple requests with C# HttpListener.
you can do something like this :
public void ListenTraces()
{
httpListener.Prefixes.Add(PORT_HOST);
try
{
httpListener.Start();
}
catch (HttpListenerException hlex)
{
log.Warn("Can't start the agent to listen transaction" + hlex);
return;
}
log.Info("Now ready to receive traces...");
while (true)
{
var context = httpListener.GetContext(); // get te context
log.Info("New trace connexion incoming");
Console.WriteLine(context.SomethingYouWant);
}
}
Related
I have this Windows form app that wants to receive some calls from some external source.
I did some example based on this :
https://learn.microsoft.com/en-us/dotnet/api/system.net.httplistener?view=net-5.0
Its almost the same thing, i just did it to run on another thread.
private static Form1 form;
public static Thread httpServer;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
form = new Form1();
form.Load += OnFormLoad;
Application.Run(form);
}
private static void OnFormLoad(object sender, EventArgs e)
{
httpServer = CreateHttp();
}
private static Thread CreateHttp()
{
HttpListener listener = new HttpListener();
string[] prefixes = new string[1];
prefixes[0] = "http://+:3070/";
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
var listeningThread = new Thread(() =>
{
while (true)
{
HttpListenerContext context = listener.GetContext();
ThreadPool.QueueUserWorkItem(param =>
{
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
string url = request.RawUrl;
string responseString = "<HTML><BODY> Hello World </BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}, null);
}
});
listeningThread.IsBackground = true;
listeningThread.Start();
return listeningThread;
}
When I call from localhost:3070 or 127.0.0.1:3070 it works, but if i try from ipadress:3070 I only get timeouts.
I'm already included this "3070" ports in my firewall....I also tried turning off my entire firewall
Also checked if the listener is working with the command :
netstat -na | find "3070"
TCP 0.0.0.0:3070 0.0.0.0:0 LISTENING
TCP [::]:3070 [::]:0 LISTENING
And also checked if this url is reserved with the command:
"netsh http show urlacl"
URL reservada : http://+:3070/
Usuário: \Todos
Escutar: Yes
Delegar: No
SDDL: D:(A;;GX;;;WD)
Anything I'm missing ?
I've created a small app to get http/https responses:
public static void Listener1(string[] prefixes)
{
if (!HttpListener.IsSupported)
{
Console.WriteLine("Seu ambiente não suporta os recursos da classe HttpListener.");
return;
}
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
Console.WriteLine("Listening...");
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
string responseString = "<HTML><BODY> Hello world </BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
listener.Stop();
}
And I'm using this prefixes:
string[] url = { "http://localhost:5324/", "https://localhost:5325/" };
When I type http://localhost:5324/ on Chrome, I get the right response, but when using https://localhost:5325/, nothing happens. Not even errors about certificates.
I've googled a lot about sending a file from a console application using an own HTTP listener self-hosted to a web application that hosted on ASP.NET MVC5 I've found a method in response named res.SendFileAsync, but I don't know how to use it. Here's my code:
public void Configuration(IAppBuilder app)
{
app.UseHandlerAsync((req, res) =>
{
Console.Clear();
foreach (var item in req.Headers)
{
Console.WriteLine(item.Key + ":" );
foreach (var item1 in item.Value)
{
Console.Write(item1);
}
}
//res.Headers.AcceptRanges.Add("bytes");
//result.StatusCode = HttpStatusCode.OK;
//result.Content = new StreamContent(st);
//result.Content.Headers.ContentLength = st.Length;
res.Headers.Add("ContentType" ,new string[]{"application/octet-stream"});
res.SendFileAsync(Directory.GetCurrentDirectory() + #"\1.mp3");
// res.ContentType = "text/plain";
return res.WriteAsync("Hello, World!");
});
}
This is an own startup class that handles HTTP requests.
There is a full tutorial here which will cover all of your needs, basically to save you time, if you want to send a byte[] to all your clients (which is how you should send a file) it should look like this:
static void Main(string[] args) {
//---listen at the specified IP and port no.---
Console.WriteLine("Listening...");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT_NO));
serverSocket.Listen(4); //the maximum pending client, define as you wish
serverSocket.BeginAccept(new AsyncCallback(acceptCallback), null);
//normally, there isn't anything else needed here
string result = "";
do {
result = Console.ReadLine();
if (result.ToLower().Trim() != "exit") {
byte[] bytes = null;
//you can use `result` and change it to `bytes` by any mechanism which you want
//the mechanism which suits you is probably the hex string to byte[]
//this is the reason why you may want to list the client sockets
foreach(Socket socket in clientSockets)
socket.Send(bytes); //send everything to all clients as bytes
}
} while (result.ToLower().Trim() != "exit");
}
I'd recommend you to delve deeper into the post and understand the entire process, see if it fits your solution.
I have a HttpListener which I want to not shut down after each request, so I'm using BeginGetContext to retrieve requests asynchronously. It's just not working properly.
Main starts properly, finding and assigning my IP address for the StartListening() function. However, when I get to listener.BeginGetContext(new AsyncCallback(OnRequest), listener); in StartListening() and it jumps to Response.StartListening(ips); in Main and then just stops. I'm not sure why. Any hints?
Here's what I have so far.
This is where I start listening for requests:
public static void StartListening(string[] prefixes)
{
HttpListener listener = new HttpListener();
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
foreach (string s in prefixes)
{
listener.Prefixes.Add("http://" + s + "/");
}
listener.Start();
Console.WriteLine("\nListening...");
listener.BeginGetContext(new AsyncCallback(OnRequest), listener);
}
And here's where I handle the requests:
public static void OnRequest(IAsyncResult result)
{
HttpListener listener = (HttpListener) result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
string url = context.Request.RawUrl;
string[] split = url.Split('/');
int lastIndex = split.Length - 1;
int x, y, z;
x = Convert.ToInt32(split[lastIndex]);
y = Convert.ToInt32(split[lastIndex - 1]);
z = Convert.ToInt32(split[lastIndex - 2]);
HttpListenerResponse response = context.Response;
Regex imageRegex = new Regex(#"SomethingSomething");
var matches = imageRegex.Match(url);
if (matches.Success)
{
string path = #"C:\SomeDir";
path = String.Format(path, matches.Groups[1].Captures[0],
matches.Groups[2].Captures[0],
matches.Groups[3].Captures[0]);
// Load the image
Bitmap bm = new Bitmap(path);
MemoryStream bmStream = new MemoryStream();
bm.Save(bmStream, ImageFormat.Png);
byte[] buffer = bmStream.ToArray();
// Get a response stream and write the response to it.
response.ContentLength64 = bmStream.Length;
response.ContentType = "image/png";
response.KeepAlive = true;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
listener.Stop();
}
response.Close();
listener.BeginGetContext(new AsyncCallback(OnRequest), listener);
}
And here's my main:
class Program
{
static void Main(string[] args)
{
string name = (args.Length < 1) ? Dns.GetHostName() : args[0];
try
{ //Find the IPv4 address
IPAddress[] addrs = Array.FindAll(Dns.GetHostEntry(string.Empty).AddressList,
a => a.AddressFamily == AddressFamily.InterNetwork);
Console.WriteLine("Your IP address is: ");
foreach (IPAddress addr in addrs)
Console.WriteLine("{0} {1}", name, addr);
//Automatically set the IP address
string[] ips = addrs.Select(ip => ip.ToString()).ToArray();
Response.StartListening(ips);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
After BeginGetContext, it fetches requests asynchronously, so it does not block the calling thread (the Main thread, in this case). And because it doesn't block it, the Main thread ends and thus your program also ends, because it's the Main thread.
You can fix this, by using a ManualResetEvent (in the System.Threading namespace). This blocks the Main thread.
class Program
{
public static ManualResetEvent ServerManualResetEvent;
static void Main(string[] args)
{
try
{
// your code to start the server
ServerManualResetEvent = new ManualResetEvent(false);
ServerManualResetEvent.WaitOne();
}
catch
{
// your catch code
}
}
}
Now the Main thread is blocked and your program only stops if you close it, or if you stop it from code:
Program.ServerManualResetEvent.Set();
Then it does not block the Main thread anymore.
I've been writing a server for an app of mine. Due to suggestions, I decided to use HttpListener to listen for incoming connections in an async method. My current code is as following:
public static async void StartServerAsync()
{
while (true)
{
Console.WriteLine("Waiting for client.. ");
var context = await listener.GetContextAsync();
Console.WriteLine("Client connected!");
// ReSharper disable once CSharpWarnings::CS4014
Task.Factory.StartNew(() => ProcessClient(context));
}
listener.Close();
}
This method is started with this:
public static void ServerBoot()
{
listener.Prefixes.Add("http://localhost:1000/");
listener.Start();
StartServerAsync();
}
The ProcessClient() method is as following:
private static void ProcessClient(HttpListenerContext context)
{
try
{
var request = context.Request;
string response;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
{
response = reader.ReadToEnd();
}
Console.WriteLine("Got command: {0}", response);
}
catch (WebException)
{
Console.WriteLine("Error reading string, closing..");
return;
}
}
Right now it's only supposed to get the string posted. However, when I run the client with this code:
Console.WriteLine(" -- Bagrut Client -- ");
Console.Write("Enter IP of server to connect to: ");
// ReSharper disable once AssignNullToNotNullAttribute
var ip = Console.ReadLine();
WebClient client = new WebClient();
var response = client.UploadString(ip, "query");
Console.WriteLine("Type of response is {0}", response);
the server does not do anything. As you can see in ProcessClient(), and in the server loop itself, it should at least say something when a client connects. However, when the code is run, nothing happens. Am I doing something wrong?
EDIT: new code:
public static void ServerBoot()
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://localhost:1337/");
listener.Start();
StartServerAsync(listener).ContinueWith(task => { });
}
private static void ProcessClient(HttpListenerContext context)
{
try
{
var request = context.Request;
string response;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
{
response = reader.ReadToEnd();
}
Console.WriteLine("Got command: {0}", response);
}
catch (WebException)
{
Console.WriteLine("Error reading string, closing..");
return;
}
}
private static async Task StartServerAsync(HttpListener listener)
{
while (true)
{
Console.WriteLine("Waiting for client.. ");
var context = await listener.GetContextAsync();
Console.WriteLine("Client connected!");
// ReSharper disable once CSharpWarnings::CS4014
Task.Factory.StartNew(() => StartServerAsync(listener));
ProcessClient(context);
await StartServerAsync(listener);
}
listener.Close();
}