HTTP Listener not getting external calls - c#

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 ?

Related

Getting a response from the browser (HTTPS, C#)

It is necessary to receive data from the browser, I mean the authorization code. I use the OAuth2 from Yahoo service. This code is displayed in the address bar of the browser after successful authorization, than redirect to redirect_uri=.... Process is used to start the browser, after that I try to listen on port XXXX with HttpListener, however even if I get some response, it is a meaningless set of characters . (UTF-8, etc. tried, the result is the same)
How can I get the authorization code from the browser after successful authorization?
Code with HttpListener
static void SniffPort()
{
byte[] input = new byte[] { 1 };
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.Bind(new IPEndPoint(IPAddress.Broadcast, 5000));
socket.IOControl(IOControlCode.ReceiveAll, input, null);
byte[] buffer = new byte[4096];
Task.Factory.StartNew(() =>
{
while (true)
{
int len = socket.Receive(buffer);
if (len <= 40) continue;
string bin = Encoding.Default.GetString(buffer, 0, len);
Console.WriteLine(bin);
}
});
}
static HttpListener _httpListener = new HttpListener();
static void Main(string[] args)
{
Console.WriteLine("Starting server...");
_httpListener.Prefixes.Add("https://localhost:5000/");
_httpListener.Start();
Console.WriteLine("Server started.");
SniffPort();
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Users\User\Desktop\chrome-win\chrome.exe");
startInfo.WindowStyle = ProcessWindowStyle.Normal;
Process p = new Process();
startInfo.Arguments = "--app=https://api.login.yahoo.com/oauth2/request_auth?client_id=CLIENT_ID&redirect_uri=https://localhost:5000/&response_type=code&language=en-us";
p.StartInfo = startInfo;
p.Start();
p.WaitForExit();
}
Also I had idea with the FiddlerCore, but after using it, you have to change the settings related to the proxy in inetcpl.cpl. It also doesn't work if the browser remembers the user and logs in immediately after starting the browser, FiddlerCore does not provide this information.
Code with FiddlerCore
public class HttpProxy : IDisposable
{
public HttpProxy()
{
Fiddler.FiddlerApplication.BeforeRequest += FiddlerApplication_BeforeRequest;
Fiddler.FiddlerApplication.Startup(5000, true, false);
}
void FiddlerApplication_BeforeRequest(Fiddler.Session oSession)
{
Console.WriteLine(String.Format("REQ: {0}", oSession.url));
}
public void Dispose()
{
Fiddler.FiddlerApplication.Shutdown();
}
}
static HttpListener _httpListener = new HttpListener();
static void Main(string[] args)
{
HttpProxy httpProxy = new HttpProxy();
//Launching the browser as in the code above.
}

C# - What's the best way to use TcpListener (async)

I would create a tcp server with TcpListener, but I don't know what's the best solution to do that.
I tried with 3 examples. See below.
Example 1
(I used BeginAcceptTcpClient)
class Program
{
static void Main(string[] args)
{
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4567);
var listener = new TcpListener(endPoint);
listener.Start();
AcceptTcpClient(listener);
while (true)
{
}
}
public static void AcceptTcpClient(TcpListener listener)
{
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
public static void ClientConnected(IAsyncResult asyncResult)
{
var listener = (TcpListener)asyncResult.AsyncState;
var client = listener.EndAcceptTcpClient(asyncResult);
AcceptTcpClient(listener);
DoAsync(client);
}
}
Example 2
(I used BeginAcceptTcpClient with AutoResetEvent)
class Program1
{
private static readonly AutoResetEvent CONNECTION_WAIT_HANDLE = new AutoResetEvent(false);
static void Main(string[] args)
{
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4567);
var listener = new TcpListener(endPoint);
listener.Start();
while (true)
{
listener.BeginAcceptTcpClient(ClientConnectedHandle, listener);
CONNECTION_WAIT_HANDLE.WaitOne();
CONNECTION_WAIT_HANDLE.Reset();
}
}
public static void ClientConnectedHandle(IAsyncResult asyncResult)
{
var listener = (TcpListener)asyncResult.AsyncState;
var client = listener.EndAcceptTcpClient(asyncResult);
CONNECTION_WAIT_HANDLE.Set();
DoAsync(client);
}
}
Example 3
(I used AcceptTcpClientAsync)
class Program2
{
static async Task Main(string[] args)
{
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4567);
var listener = new TcpListener(endPoint);
listener.Start();
while (true)
{
var client = await listener.AcceptTcpClientAsync();
DoAsync(client);
}
}
public static void AcceptTcpClient(TcpListener listener)
{
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
public static void ClientConnected(IAsyncResult asyncResult)
{
var listener = (TcpListener)asyncResult.AsyncState;
var client = listener.EndAcceptTcpClient(asyncResult);
AcceptTcpClient(listener);
DoAsync(client);
}
}
I think the best solution is the last (Example 3) but I'm not sure. What do you think of that?
This is the code that I'm using in my project. It's a receive only asynchronous server but you can modify it to your liking according to your needs in Task.Run(). I have commented out the code so that you can understand how it works.
static async Task Main(string[] args)
{
await RunServer();
}
static async Task RunServer()
{
TcpListener Listener = new TcpListener(IPAddress.Any, YOURPORTHERE); // Set your listener
Listener.Start(); // Start your listener
while (true) // Permanent loop, it may not be the best solution
{
TcpClient Client = await Listener.AcceptTcpClientAsync(); // Waiting for a connection
_ = Task.Run(() => { // Connection opened. Queues the specified job to run in the ThreadPool, meanwhile the server is ready to accept other connections in parallel
try
{
var Stream = Client.GetStream(); // (read-only) get data bytes
if (Stream.CanRead) // Verify if the stream can be read.
{
byte[] Buffer = new byte[Client.ReceiveBufferSize]; // Initialize a new empty byte array with the data length.
StringBuilder SB = new StringBuilder();
do // Start converting bytes to string
{
int BytesReaded = Stream.Read(Buffer, 0, Buffer.Length);
SB.AppendFormat("{0}", Encoding.ASCII.GetString(Buffer, 0, BytesReaded));
} while (Stream.DataAvailable); // Until stream data is available
if (SB != null) // Stream data is ready and converted to string
// Do some stuffs
}
}
catch (Exception Ex) // In case of errors catch it to avoid the app crash
{
ConsoleMessage.Error(Ex.ToString()); // Detailed exception
}
});
}
}

HttpListener BeginGetContext suddenly stopping?

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.

Use of HttpListener

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);
}
}

How would I constant listen on a port with a GUI?

I am trying to learn TCP server/client interaction. I want to know how I would listen to a port all the time with GUI. Currently I am using this code:
private void Form1_Load(object sender, EventArgs e)
{
CreateServer();
}
void CreateServer()
{
TcpListener tcp = new TcpListener(25565);
tcp.Start();
Thread t = new Thread(() =>
{
while (true)
{
var tcpClient = tcp.AcceptTcpClient();
ThreadPool.QueueUserWorkItem((_) =>
{
Socket s = tcp.AcceptSocket();
console.Invoke((MethodInvoker)delegate { console.Text += "Connection esatblished: " + s.RemoteEndPoint + Environment.NewLine; });
byte[] b = new byte[100];
int k = s.Receive(b);
for (int i = 0; i < k; i++)
{
console.Text += Convert.ToChar(b[i]);
incoming += Convert.ToChar(b[i]);
}
MessageBox.Show(incoming);
console.Invoke((MethodInvoker)delegate { console.Text += incoming + Environment.NewLine; });
list.Invoke((MethodInvoker)delegate { list.Items.Add(incoming); });
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("\n"));
tcpClient.Close();
}, null);
}
});
t.IsBackground = true;
t.Start();
}
Any help would be much appreciateed.
Short answer - run TCP listener in the separate Thread/Task (TPL).
For full working solution you also have to implement dispatching of the any changes to UI form separate thread to main thread using special technique which is depends on Framework you are using, I mean WPF/WinForms/whatever.
Code below works for me fine. Read TODO section before.
TODO:
Add to form Textbox, ListBox, Button, make public:
public System.Windows.Forms.TextBox console;
public System.Windows.Forms.ListBox incommingMessages;
private System.Windows.Forms.Button sendSampleDataButton;
Entry point:
private static Form1 form;
[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)
{
CreateServer();
}
Server:
private static void CreateServer()
{
var tcp = new TcpListener(IPAddress.Any, 25565);
tcp.Start();
var listeningThread = new Thread(() =>
{
while (true)
{
var tcpClient = tcp.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(param =>
{
NetworkStream stream = tcpClient.GetStream();
string incomming;
byte[] bytes = new byte[1024];
int i = stream.Read(bytes, 0, bytes.Length);
incomming = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
form.console.Invoke(
(MethodInvoker)delegate
{
form.console.Text += String.Format(
"{0} Connection esatblished: {1}{2}",
DateTime.Now,
tcpClient.Client.RemoteEndPoint,
Environment.NewLine);
});
MessageBox.Show(String.Format("Received: {0}", incomming));
form.incommingMessages.Invoke((MethodInvoker)(() => form.incommingMessages.Items.Add(incomming)));
tcpClient.Close();
}, null);
}
});
listeningThread.IsBackground = true;
listeningThread.Start();
}
Client
private void button1_Click(object sender, EventArgs e)
{
Connect("localhost", "hello localhost " + Guid.NewGuid());
}
static void Connect(String server, String message)
{
try
{
Int32 port = 25565;
TcpClient client = new TcpClient(server, port);
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
stream.Close();
client.Close();
}
catch (ArgumentNullException e)
{
Debug.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Debug.WriteLine("SocketException: {0}", e);
}
}
Screenshot:
Create a thread, start to listen in it & don't stop the server
void CreateServer()
{
TcpListener tcp = new TcpListener(25565);
tcp.Start();
Thread t = new Thread(()=>
{
while (true)
{
var tcpClient = tcp.AcceptTcpClient();
ThreadPool.QueueUserWorkItem((_) =>
{
//Your server codes handling client's request.
//Don't access UI control directly here
//Use "Invoke" instead.
tcpClient.Close();
},null);
}
});
t.IsBackground = true;
t.Start();
}
You could use the threads approach (as mentioned by other answers) or use asynchronous sockets, which in my opnion is way better. And even better, you can use the async model proposed by SocketAsyncEventArgs.
Async sockets will take benefits from using completion ports.
here is a good example on mdsn: Asynchronous server socket example

Categories