Remote control with TcpListener

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
 
L

Laxmikant Rashinkar

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()
 
M

MuZZy

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
 

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