Remote control with TcpListener

  • Thread starter Thread starter MuZZy
  • Start date Start date
M

MuZZy

Hi,

The app i develop supose to have a remote control/reporting feature,
so that if a client connects to it, he can obtain information about application state and to send some commands.

I started with using TcpListener in a separate thread of the app.
Something like this:

// ============================ CODE BEGIN =======================
public void ListenerThreadFunction()
{
RemServer = new TcpListener(IPAddress.Parse("127.0.0.1"),9999);
RemServer.Start();

// Buffer for reading data
Byte[] bytes = new Byte[65535];
String data = null;

while(true)
{
// Get the client connection
TcpClient client = RemServer.AcceptTcpClient();
// Get the connection stream
NetworkStream stream = client.GetStream();
int i;
// Loop to get all the data client sent
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
// Convert dada to string
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
data = data.ToUpper().Trim();

// Now check what command arrived:

// Client asks to provide list of recorders
if (data == "GET_RECORDERS_LIST")
{
// Form return string in format

}
}
client.Close();
}
}

// ===================== CODE END ========================

It's partially taken from a MSDN example.

The idea how i see it should be this: client connects, sends a request, listener responds, then client sends another request, server responds, and so on.

The first problem i see is that server will be blocked waiting for 65535 bytes of data from client in stream.Read()
Second, i'm not sure how i should correctly design the loops in the function.

Any ideas would be appreciated!

Thank you,
Andrey
 
Hi,

Your server code blocks on the call to read 65535 bytes of data.
At some point in time, the client sends the server a request packet,
consisting
of 100 bytes (for example). On the server side, the call while((i =
stream.Read(bytes, 0, bytes.Length))!=0)
will then return (unblock) and i will equal 100. So that solves your
blocking problem.

Now, about parsing the command that the client has sent you. I would use
integers instead
of strings to represent the commands. Let us assume the client can send us 5
possible commands as follows:

1 = GET_RECORDERS_LIST
2 = GET_DRUMS_LIST
3 = GET_GUITARS_LIST
4 = GET_FLUTES_LIST
5 = GET_SAXPHONES_LIST

I would first declare a delegate as follows: delegate int
ClientCmdHandler();
Then I would declare an array of event handlers to hold my 5 commands, as
follows:

ClientCmdHandler[] executeClientCmd = new ClientCmdHandler[5];
executeClientCmd[0] = new ClientCmdHandler(getRecordersList);
executeClientCmd[1] = new ClientCmdHandler(getDrumsList);
executeClientCmd[2] = new ClientCmdHandler(getGuitarsList);
executeClientCmd[3] = new ClientCmdHandler(getFlutesList);
executeClientCmd[4] = new ClientCmdHandler(getSaxphonesList);

then I would declare the following methods as follows

public int (getRecordersList) { do something useful here }
public int (getDrumsList) { do something useful here }
public int (getGuitarsList) { do something useful here }
public int (getFlutesList) { do something useful here }
public int (getSaxphonesList) { do something useful here }

Once I have retrieved the cmd from the client packet, I would do as follows

if( (cmd > 0) && (cmd < 6) )
{
executeClientCmd[cmd - 1](); // this will call the corresponding
commands method
}

hope this helps
LK

even though you are blocking on the buffer size of 65536 bytes, the call
will return when fewer bytes are read
MuZZy said:
Hi,

The app i develop supose to have a remote control/reporting feature,
so that if a client connects to it, he can obtain information about
application state and to send some commands.
I started with using TcpListener in a separate thread of the app.
Something like this:

// ============================ CODE BEGIN =======================
public void ListenerThreadFunction()
{
RemServer = new TcpListener(IPAddress.Parse("127.0.0.1"),9999);
RemServer.Start();

// Buffer for reading data
Byte[] bytes = new Byte[65535];
String data = null;

while(true)
{
// Get the client connection
TcpClient client = RemServer.AcceptTcpClient();
// Get the connection stream
NetworkStream stream = client.GetStream();
int i;
// Loop to get all the data client sent
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
// Convert dada to string
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
data = data.ToUpper().Trim();

// Now check what command arrived:

// Client asks to provide list of recorders
if (data == "GET_RECORDERS_LIST")
{
// Form return string in format

}
}
client.Close();
}
}

// ===================== CODE END ========================

It's partially taken from a MSDN example.

The idea how i see it should be this: client connects, sends a request,
listener responds, then client sends another request, server responds, and
so on.
The first problem i see is that server will be blocked waiting for 65535
bytes of data from client in stream.Read()
 
Laxmikant said:
Hi,

Your server code blocks on the call to read 65535 bytes of data.
At some point in time, the client sends the server a request packet,
consisting
of 100 bytes (for example). On the server side, the call while((i =
stream.Read(bytes, 0, bytes.Length))!=0)
will then return (unblock) and i will equal 100. So that solves your
blocking problem.

Thank you for response!
Now i re-read the MSDN article and see that it says that if NO data is available it will block.
So it answers my question! Thanks a lot!
Now, about parsing the command that the client has sent you. I would use
integers instead
of strings to represent the commands. Let us assume the client can send us 5
possible commands as follows:

1 = GET_RECORDERS_LIST
2 = GET_DRUMS_LIST
3 = GET_GUITARS_LIST
4 = GET_FLUTES_LIST
5 = GET_SAXPHONES_LIST

I would first declare a delegate as follows: delegate int
ClientCmdHandler();
Then I would declare an array of event handlers to hold my 5 commands, as
follows:

ClientCmdHandler[] executeClientCmd = new ClientCmdHandler[5];
executeClientCmd[0] = new ClientCmdHandler(getRecordersList);
executeClientCmd[1] = new ClientCmdHandler(getDrumsList);
executeClientCmd[2] = new ClientCmdHandler(getGuitarsList);
executeClientCmd[3] = new ClientCmdHandler(getFlutesList);
executeClientCmd[4] = new ClientCmdHandler(getSaxphonesList);

then I would declare the following methods as follows

public int (getRecordersList) { do something useful here }
public int (getDrumsList) { do something useful here }
public int (getGuitarsList) { do something useful here }
public int (getFlutesList) { do something useful here }
public int (getSaxphonesList) { do something useful here }

Once I have retrieved the cmd from the client packet, I would do as follows

if( (cmd > 0) && (cmd < 6) )
{
executeClientCmd[cmd - 1](); // this will call the corresponding
commands method
}

hope this helps
LK

even though you are blocking on the buffer size of 65536 bytes, the call
will return when fewer bytes are read
Hi,

The app i develop supose to have a remote control/reporting feature,
so that if a client connects to it, he can obtain information about

application state and to send some commands.
I started with using TcpListener in a separate thread of the app.
Something like this:

// ============================ CODE BEGIN =======================
public void ListenerThreadFunction()
{
RemServer = new TcpListener(IPAddress.Parse("127.0.0.1"),9999);
RemServer.Start();

// Buffer for reading data
Byte[] bytes = new Byte[65535];
String data = null;

while(true)
{
// Get the client connection
TcpClient client = RemServer.AcceptTcpClient();
// Get the connection stream
NetworkStream stream = client.GetStream();
int i;
// Loop to get all the data client sent
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
// Convert dada to string
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
data = data.ToUpper().Trim();

// Now check what command arrived:

// Client asks to provide list of recorders
if (data == "GET_RECORDERS_LIST")
{
// Form return string in format

}
}
client.Close();
}
}

// ===================== CODE END ========================

It's partially taken from a MSDN example.

The idea how i see it should be this: client connects, sends a request,

listener responds, then client sends another request, server responds, and
so on.
The first problem i see is that server will be blocked waiting for 65535

bytes of data from client in stream.Read()
Second, i'm not sure how i should correctly design the loops in the
function.

Any ideas would be appreciated!

Thank you,
Andrey
 
Back
Top