Asynchronsis socket or threads

D

Dan Holmes

The following is the start of an application that will eventually run as
a service. It listens on port 23 and emulates VT100. I would like some
feedback on the network stream reading and writing. I don't really know
if this is the correct approach for what i am trying.

I have telnet clients that i am controlling. I don't want the
processing of the input of one terminal to stop another terminal from
processing.

I think i have things right up until the ProcessMessageFromTerminal method.

any input is greatly appreciated. Also any links or books on this
subject would be handy as well.

dan

using System;
using System.Collections.Generic;
using System.Text;
using SNS = System.Net.Sockets;
namespace IVS.Framework.RF
{
class Multiplexor
{
static class VT100Commands
{
public static const string esc = 0x1b;
public static const string CLRSCRN = esc + "[2J";
public static const string REVERSE = esc + "[7m";
public static const string CLREOL = esc + "[K";
public static const string CLREOS = esc + "[J";
public static const string REGULAR = esc + "[0m";
public static const string HOME = esc + "[H";
public static const string LOCKKBD = esc + "[2h";
public static const string UNLOCKKBD = esc + "[2l";
public static const string UNDERLINE = esc + "[4m";
}
List<RFProcess> rfProcesses = null;
public Multiplexor()
{
rfProcesses = new List<RFProcess>();
}
static void Main(string[] args)
{
Multiplexor mux = new Multiplexor();
WriteUsage();

SNS.TcpListener listn = new
SNS.TcpListener(System.Net.IPAddress.Any, 23);
listn.Start();
IAsyncResult ar = listn.BeginAcceptTcpClient(new
AsyncCallback(mux.ProcessSocket), listn);

bool keepGoing = true;
do
{
ConsoleKeyInfo c = System.Console.ReadKey();
switch (c.Key)
{
case ConsoleKey.X:
keepGoing = false;
break;
}
} while (keepGoing);
}
static void WriteUsage()
{
Console.WriteLine("Press 'x' to close");
}
private void ProcessSocket(IAsyncResult ar)
{
RFProcess rf = new RFProcess();

SNS.TcpListener listener = (SNS.TcpListener)ar.AsyncState;
rf.Socket = listener.EndAcceptTcpClient(ar);
listener.BeginAcceptTcpClient(new
AsyncCallback(ProcessSocket), listener);

Console.WriteLine("Client connected completed");
WriteToClient(rf.Socket, VT100Commands.CLRSCRN +
"connecting...");
lock (rfProcesses)
{
rfProcesses.Add(rf);
}

}
public static void WriteToClient(SNS.TcpClient client, string
message)
{
client.GetStream().Write(Encoding.ASCII.GetBytes(message),
0, message.Length);
}
}
class RFProcess
{
const int BufferSize = 512;
byte[] recvBuffer = new byte[BufferSize];
StringBuilder buffer = new StringBuilder();
SNS.TcpClient _socket = null;

public SNS.TcpClient Socket
{
get { return _socket; }
set {
_socket = value;
_socket.GetStream().BeginRead(recvBuffer, 0,
recvBuffer.Length
, new AsyncCallback(ProcessMessageFromTerminal), this);
}
}
private void ProcessMessageFromTerminal(IAsyncResult ar)
{
RFProcess me = (RFProcess)ar.AsyncState;
SNS.NetworkStream ns = me.Socket.GetStream();
int bytesRead = ns.EndRead(ar);
buffer.Append(Encoding.ASCII.GetString(readBuffer, 0,
bytesRead));
//this is currently an echo. i will replace this will application
logic later.
Multiplexor.WriteToClient(me.Socket, buffer.ToString());
ns.BeginRead(recvBuffer, 0, recvBuffer.Length
, new AsyncCallback(ProcessMessageFromTerminal), me);
}

}
}
 
N

Nicholas Paldino [.NET/C# MVP]

Dan,

Without any idea of what it is you are trying to do, or what you think
the error is, it's difficult to say just by looking at the code.

You need to provide more information.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Dan Holmes said:
The following is the start of an application that will eventually run as a
service. It listens on port 23 and emulates VT100. I would like some
feedback on the network stream reading and writing. I don't really know
if this is the correct approach for what i am trying.

I have telnet clients that i am controlling. I don't want the processing
of the input of one terminal to stop another terminal from processing.

I think i have things right up until the ProcessMessageFromTerminal
method.

any input is greatly appreciated. Also any links or books on this subject
would be handy as well.

dan

using System;
using System.Collections.Generic;
using System.Text;
using SNS = System.Net.Sockets;
namespace IVS.Framework.RF
{
class Multiplexor
{
static class VT100Commands
{
public static const string esc = 0x1b;
public static const string CLRSCRN = esc + "[2J";
public static const string REVERSE = esc + "[7m";
public static const string CLREOL = esc + "[K";
public static const string CLREOS = esc + "[J";
public static const string REGULAR = esc + "[0m";
public static const string HOME = esc + "[H";
public static const string LOCKKBD = esc + "[2h";
public static const string UNLOCKKBD = esc + "[2l";
public static const string UNDERLINE = esc + "[4m";
}
List<RFProcess> rfProcesses = null;
public Multiplexor()
{
rfProcesses = new List<RFProcess>();
}
static void Main(string[] args)
{
Multiplexor mux = new Multiplexor();
WriteUsage();

SNS.TcpListener listn = new
SNS.TcpListener(System.Net.IPAddress.Any, 23);
listn.Start();
IAsyncResult ar = listn.BeginAcceptTcpClient(new
AsyncCallback(mux.ProcessSocket), listn);

bool keepGoing = true;
do
{
ConsoleKeyInfo c = System.Console.ReadKey();
switch (c.Key)
{
case ConsoleKey.X:
keepGoing = false;
break;
}
} while (keepGoing);
}
static void WriteUsage()
{
Console.WriteLine("Press 'x' to close");
}
private void ProcessSocket(IAsyncResult ar)
{
RFProcess rf = new RFProcess();

SNS.TcpListener listener = (SNS.TcpListener)ar.AsyncState;
rf.Socket = listener.EndAcceptTcpClient(ar);
listener.BeginAcceptTcpClient(new
AsyncCallback(ProcessSocket), listener);

Console.WriteLine("Client connected completed");
WriteToClient(rf.Socket, VT100Commands.CLRSCRN +
"connecting...");
lock (rfProcesses)
{
rfProcesses.Add(rf);
}

}
public static void WriteToClient(SNS.TcpClient client, string
message)
{
client.GetStream().Write(Encoding.ASCII.GetBytes(message), 0,
message.Length);
}
}
class RFProcess
{
const int BufferSize = 512;
byte[] recvBuffer = new byte[BufferSize];
StringBuilder buffer = new StringBuilder();
SNS.TcpClient _socket = null;

public SNS.TcpClient Socket
{
get { return _socket; }
set {
_socket = value;
_socket.GetStream().BeginRead(recvBuffer, 0,
recvBuffer.Length
, new AsyncCallback(ProcessMessageFromTerminal),
this);
}
}
private void ProcessMessageFromTerminal(IAsyncResult ar)
{
RFProcess me = (RFProcess)ar.AsyncState;
SNS.NetworkStream ns = me.Socket.GetStream();
int bytesRead = ns.EndRead(ar);
buffer.Append(Encoding.ASCII.GetString(readBuffer, 0,
bytesRead));
//this is currently an echo. i will replace this will application logic
later.
Multiplexor.WriteToClient(me.Socket, buffer.ToString());
ns.BeginRead(recvBuffer, 0, recvBuffer.Length
, new AsyncCallback(ProcessMessageFromTerminal), me);
}

}
}
 
D

Dan Holmes

Nicholas said:
Dan,

Without any idea of what it is you are trying to do, or what you think
the error is, it's difficult to say just by looking at the code.

You need to provide more information.
There isn't an error yet (i don't think). What i want to know i guess
is how reading asynchronously from a network stream is different from
creating threads out of each of the connections?

When a message comes in from the telnet client i need to handle the
process that is requested. I don't want the processing of one client to
block processing of another client or accepting a connection from
another client.

The critical code (i think) is the ProcessMessageFromTerminal method in
RFProcess. Does the code between the EndRead and BeginRead require
completion before another client can finish?

dan

This is a version that will compile and accept connections from a telnet
client.

using System;
using System.Collections.Generic;
using System.Text;
using SNS = System.Net.Sockets;
namespace IVS.Framework.RF
{
internal class VT100Commands
{
public readonly char esc;
public readonly string CLRSCRN;
public readonly string REVERSE;
public readonly string CLREOL;
public readonly string CLREOS;
public readonly string REGULAR;
public readonly string HOME;
public readonly string LOCKKBD;
public readonly string UNLOCKKBD;
public readonly string UNDERLINE;
public VT100Commands()
{
esc = (char)0x1b;
CLRSCRN = esc + "[2J";
REVERSE = esc + "[7m";
CLREOL = esc + "[K";
CLREOS = esc + "[J";
REGULAR = esc + "[0m";
HOME = esc + "[H";
LOCKKBD = esc + "[2h";
UNLOCKKBD = esc + "[2l";
UNDERLINE = esc + "[4m";
}
}
class Multiplexor : IDisposable
{
List<RFProcess> rfProcesses = null;
public Multiplexor()
{
rfProcesses = new List<RFProcess>();
}
static void Main(string[] args)
{
Multiplexor mux = new Multiplexor();
WriteUsage();

SNS.TcpListener listn = new
SNS.TcpListener(System.Net.IPAddress.Any, 23);
listn.Start();
IAsyncResult ar = listn.BeginAcceptTcpClient(new
AsyncCallback(mux.ProcessSocket), listn);

bool keepGoing = true;
do
{
ConsoleKeyInfo c = System.Console.ReadKey();
switch (c.Key)
{
case ConsoleKey.X:
keepGoing = false;
break;
}
} while (keepGoing);
listn.Stop();

}
static void WriteUsage()
{
Console.WriteLine("Press 'x' to close");
}
private void ProcessSocket(IAsyncResult ar)
{
VT100Commands vt = new VT100Commands();
RFProcess rf = new RFProcess();

SNS.TcpListener listener = (SNS.TcpListener)ar.AsyncState;
rf.Socket = listener.EndAcceptTcpClient(ar);
listener.BeginAcceptTcpClient(new
AsyncCallback(ProcessSocket), listener);

Console.WriteLine("Client connected completed");
WriteToClient(rf.Socket, vt.CLRSCRN + vt.HOME +
"connecting...");
lock (rfProcesses)
{
rfProcesses.Add(rf);
}

}
public static void WriteToClient(SNS.TcpClient client, string
message)
{
if (client.Connected)
{
SNS.NetworkStream ns = client.GetStream();
if (ns.CanWrite)
ns.Write(Encoding.ASCII.GetBytes(message), 0,
message.Length);
}
}
public void Dispose()
{
foreach (RFProcess rf in rfProcesses)
{
rf.Dispose();
}
}
}
class RFProcess : IDisposable
{
const int BufferSize = 512;
byte[] recvBuffer = new byte[BufferSize];
SNS.TcpClient _socket = null;

public SNS.TcpClient Socket
{
get { return _socket; }
set {
_socket = value;
_socket.GetStream().BeginRead(recvBuffer, 0,
recvBuffer.Length
, new AsyncCallback(ProcessMessageFromTerminal), this);
}
}
private void ProcessMessageFromTerminal(IAsyncResult ar)
{
RFProcess me = (RFProcess)ar.AsyncState;
SNS.NetworkStream ns = me.Socket.GetStream();
int bytesRead = ns.EndRead(ar);
try
{
Multiplexor.WriteToClient(me.Socket,
Encoding.ASCII.GetString(recvBuffer, 0, bytesRead));
}
catch
{
return;
}
if (me.Socket.Connected)
ns.BeginRead(recvBuffer, 0, recvBuffer.Length
, new
AsyncCallback(ProcessMessageFromTerminal), me);
}

public void Dispose()
{
_socket.GetStream().Close();
_socket.Close();
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top