I currently have a console app, that does two things. First is spawns a server and accepts connections on a specific port. Second it manages an external program using System.Diagnostics. For the most part it works as intended, except that on occasion it socket server will lock up and refuse new connections.
As is I need to figure out how to add in a new 'feature/function' to the socket server to simulate a console/terminal like feel to the end user. Right now, as it sits I do use async calls on the server side, but I am thinking they are not effective as they can cause lock ups. As I can only either send or receive a single line at a time. Cannot send and receive at the same time, which for my new feature/function I need to be able to do.
This is what I am working with and am open to all suggestions other than port over to C++ and write/roll my own socket api. (not experienced enough for that)
public static void ReceiveCallback(IAsyncResult AsyncCall)
{
allDone.Set();
DateTime Expir = DateTime.Now.AddSeconds(20);
// Data is send in bytes -- so we need to convert a C# string to a Byte[]
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
Byte[] message = encoding.GetBytes("MWrap API Server v" + Program.ver+"\n\r");
Byte[] message2 = encoding.GetBytes("Build: " + Program.Bver+"\n\r");
// Program p = new Program();
// The original listening socket is returned in the AsyncCall, we need to call "EndAccept" to
// receive the client socket which we can use to send and receive data.
Socket listener = (Socket)AsyncCall.AsyncState;
Socket client = listener.EndAccept(AsyncCall);
client.ReceiveTimeout = 20000;
// listener.BeginAccept(new AsyncCallback(ReceiveCallback), listener);
Stream S = new NetworkStream(client);
StreamReader sr = new StreamReader(S);
StreamWriter sw = new StreamWriter(S);
// Console.WriteLine("Received Connection from {0}", client.RemoteEndPoint);
client.Send(message);
client.Send(message2);
// End of the incoming connection
bool test = true; // Used for Inner While Loop Set to false from within after client.Close() to break full connection and disconnect client
while (client.Connected)
{
// Read lines until client tells us to stop
while (test == true)
{
string output = null;
try
{
output = sr.ReadLine().ToString();
// Console.WriteLine(output);
}
catch
{
// if the output (IE sent data to us is NULL) close the connection
test = false;
client.Close();
break;
}
// Replacing IF statments with a Switch Statment
switch (output.ToLower())
{
// All accepted commands here
default:
Send(client, "INVALID");
break;
}
}
}
// Console.WriteLine("Ending the connection");
try
{
if (client.Connected == true)
{
client.Disconnect(false);
client.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.Data.ToString());
}
//client.Close();
// At the end of the connection, we need to tell the OS that we can receive another call
}
[STAThread]
public static void Main()
{
//api_server api = new api_server();
Program.ReloadServerProperties();
start_listen();
}
public static byte[] ConvertToString(string input)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
Byte[] message = encoding.GetBytes(input+"\n\r");
return message;
}
static ManualResetEvent allDone = new ManualResetEvent(false);
static void start_listen()
{
try
{
IPAddress localAddress = IPAddress.Parse("0.0.0.0");
// Define the kind of socket we want: Internet, Stream, TCP
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Define the address we want to claim: the first IP address found earlier, at port 2200
IPEndPoint ipEndpoint = new IPEndPoint(localAddress, port);
// Bind the socket to the end point
listenSocket.Bind(ipEndpoint);
// Start listening, only allow 1 connection to queue at the same time
listenSocket.Listen(100);
//listenSocket.BeginAccept(new AsyncCallback(ReceiveCallback), listenSocket);
Console.WriteLine("API Server Created {0}", listenSocket.LocalEndPoint);
Console.WriteLine("Your External IP Address is: " + getPublicIP());
Console.WriteLine("Your Local IP is: " + localIP() );
// Start being important while the world rotates
while (true) // Required for Keep ALive
{
allDone.Reset();
listenSocket.BeginAccept(new AsyncCallback(ReceiveCallback), listenSocket);
allDone.WaitOne();
//Thread.Sleep(2000);
}
}
catch (Exception e)
{
Console.WriteLine("Caught Exception: {0}", e.ToString());
}
}
The following two functions is what sends data back to the connected client
static void Send(Socket Client, string msg){
byte[] ms = ConvertToString(msg);
Client.Send(ms);
//Client.BeginSend(ms, 0,ms.Length, 0, new AsyncCallback(SendCallBack), Client);
}
static void SendCallBack(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
allDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
So quick summery, Need to be able to continue receiving data from client while also sending data to the client as well. I've thought about using two seperate sockets, one to send and one to receive but was unsure of how to terminate the continuous send back to the client of the console output.
IE would something like this work?
public static bool consoleProc = true;
...
while(consoleProc == true){
// send data back
}
// On another connection
case "stopconsole": // receive stop command and change the public bool to false and on the next loop the stream will stop
consoleProc = false;
break;
Thanks for the help, Jon


Sign In
Create Account

Back to top









