Created
September 11, 2020 14:43
-
-
Save philipmat/238c0d075f0767c6fbcff453e4f4d479 to your computer and use it in GitHub Desktop.
Socket responder - Listens on a socket for incoming connections and responds with "I Am Up" html.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
IamupResponder.StartListening(); | |
return; | |
} | |
/// <summary> | |
/// Listens on a socket for incoming connections and responds with "I Am Up" html. | |
/// </summary> | |
/// <remarks> | |
/// Inspired by: | |
/// https://docs.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example | |
/// </remarks> | |
internal class IamupResponder | |
{ | |
private const string IamupHttpResponse = "HTTP/1.1 200 - OK\r\n" | |
+ "Content-Type: text/html\r\n" | |
+ "\r\n" | |
+ @"<html> | |
<!-- Healthcheck: To check whether web server is up --> | |
I AM UP | |
</html>"; | |
// private static readonly ILog _logger = LogManager.GetLogger(typeof(IamupResponder)); | |
// Thread signal. | |
private static ManualResetEvent AllDone = new ManualResetEvent(false); | |
public static void StartListening(int port = 7070) | |
{ | |
// IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); | |
// IPAddress ipAddress = ipHostInfo.AddressList[0]; | |
// Establish the local endpoint for the socket - listens on all IPs | |
IPAddress ipAddress = IPAddress.Parse("0.0.0.0"); | |
// IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); | |
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port); | |
// Create a TCP/IP socket. | |
Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | |
// Bind the socket to the local endpoint and listen for incoming connections. | |
try | |
{ | |
listener.Bind(localEndPoint); | |
listener.Listen(100); | |
while (true) | |
{ | |
// Set the event to nonsignaled state. | |
AllDone.Reset(); | |
// Start an asynchronous socket to listen for connections. | |
string msg = $"IAmUp Waiting for a connection on {localEndPoint}..."; | |
Console.WriteLine(msg); | |
// _logger.Info(msg); | |
listener.BeginAccept( | |
new AsyncCallback(AcceptCallback), | |
listener); | |
// Wait until a connection is made before continuing. | |
AllDone.WaitOne(); | |
} | |
} | |
catch (Exception e) | |
{ | |
// _logger.ErrorFormat("Error starting listening on {1}: {0}.", e, localEndPoint); | |
} | |
} | |
private static void AcceptCallback(IAsyncResult ar) | |
{ | |
// Signal the main thread to continue. | |
AllDone.Set(); | |
// Get the socket that handles the client request. | |
Socket listener = (Socket)ar.AsyncState; | |
Socket handler = listener.EndAccept(ar); | |
// Create the state object. | |
var state = new StateObject | |
{ | |
workSocket = handler | |
}; | |
handler.BeginReceive( | |
state.buffer, | |
offset: 0, | |
size: StateObject.BufferSize, | |
socketFlags: 0, | |
callback: new AsyncCallback(ReadCallback), | |
state: state); | |
} | |
private static void ReadCallback(IAsyncResult ar) | |
{ | |
string content = string.Empty; | |
// Retrieve the state object and the handler socket | |
// from the asynchronous state object. | |
StateObject state = (StateObject)ar.AsyncState; | |
Socket handler = state.workSocket; | |
// Read data from the client socket. | |
int bytesRead = handler.EndReceive(ar); | |
if (bytesRead > 0) | |
{ | |
string msg = $"IAmUp received {bytesRead:n0} bytes."; | |
Console.WriteLine(msg); | |
// _logger.Debug(msg); | |
// send i amp up content to requester | |
Send(handler, IamupHttpResponse); | |
} | |
} | |
private static void Send(Socket handler, string data) | |
{ | |
// Convert the string data to byte data using ASCII encoding. | |
byte[] byteData = Encoding.ASCII.GetBytes(data); | |
// Begin sending the data to the remote device. | |
handler.BeginSend( | |
byteData, | |
offset: 0, | |
size: byteData.Length, | |
socketFlags: 0, | |
callback: new AsyncCallback(SendCallback), | |
state: handler); | |
} | |
private static void SendCallback(IAsyncResult ar) | |
{ | |
try | |
{ | |
// Retrieve the socket from the state object. | |
Socket handler = (Socket)ar.AsyncState; | |
// Complete sending the data to the remote device. | |
int bytesSent = handler.EndSend(ar); | |
// Console.WriteLine("Sent {0} bytes to client.", bytesSent); | |
handler.Shutdown(SocketShutdown.Both); | |
handler.Close(); | |
} | |
catch (Exception ex) | |
{ | |
// _logger.Error("Error sending response to client: {0}", ex); | |
} | |
} | |
// State object for reading client data asynchronously | |
private class StateObject | |
{ | |
// Client socket. | |
public Socket workSocket; | |
// Size of receive buffer. | |
public const int BufferSize = 1024; | |
// Receive buffer. | |
public byte[] buffer = new byte[BufferSize]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment