tags:

views:

476

answers:

4

I have the following code for the server application:

        TcpListener recSock = new TcpListener(400);
        recSock.Start();
        TcpClient client = recSock.AcceptTcpClient();
        NetworkStream netStream = client.GetStream();

        Byte[] data = new Byte[256];

        int i;

        while((i = netStream.Read(data, 0, data.Length)) != 0) {
            string cmd = ASCIIEncoding.ASCII.GetString(data, 0, i);
            Console.WriteLine(cmd);
            if(cmd == "R") {
                RestartScheduler();
            }
        }

        client.Close();

And the client looks like:

        TcpClient client = new TcpClient();
        client.Connect("VM-SCHEDULER", 400);
        NetworkStream netStream = client.GetStream();
        Byte[] data = ASCIIEncoding.ASCII.GetBytes("R");
        netStream.Write(data, 0, data.Length);
        netStream.Flush();
        client.Close();

All is fine the first time the client connects the "R" command is read and the RestartScheduler() method is called, however all subsequent commands fail until the server is restarted.

I have used telnet to connect to the server after the first attempt and it is still listening on the port.

Where am i going wrong?

EDIT:

Basically what I am trying to accomplish is that the server will listen always, a client will then connect send the "R" command then close the connection. The client must be able to connect to the server at any time to issue the command. There will only be 1 client at any given time.

A: 

Are you connecting multiple times, or sending multiple commands down the same connection? If you could provide a short but complete program to demonstrate the problem, that would really help.

My guess is that you're running into problems due to reading multiple commands from a single connection in one go, but it's hard to know without more information. Don't forget that a single call to Write from the client can easily result in multiple reads at the server end - or vice versa.

Jon Skeet
+2  A: 

If there is no data to be read, netStream.Read will return 0 and your while loop will exit, disconnecting the client at client.Close();. You have nothing in your code to allow the server to continue receiving in this scenario.

You need to keep listening for connections until the application is shutdown, so put the listen and GetStream in a while loop. Since Stream.Read is a blocking call, you should have some data for the data reading while loop (unless timeout occurs). Otherwise it will close the connection and go back to listening for a new one.

Note: I've not included any error handling in here, you'll need to add that yourself.

    TcpListener recSock = new TcpListener(400);
    recSock.Start();

    while (!stopping)
    {
        TcpClient client = recSock.AcceptTcpClient();
        NetworkStream netStream = client.GetStream();

        Byte[] data = new Byte[256];

        int i = netStream.Read(data, 0, data.Length);

        while(i != 0) 
        {
            string cmd = ASCIIEncoding.ASCII.GetString(data, 0, i);
            Console.WriteLine(cmd);
            if(cmd == "R") {
                RestartScheduler();
            }
            i = stream.Read(bytes, 0, bytes.Length);
        }

        client.Close();

        Thread.Sleep(1); // Will allow the stopping bool to be updated
    }

Module level add:

    private bool stopping = false;

In your shutdown function:

    stopping = true;
badbod99
A: 

Well the server will exit after the first command it receives, no?

Noon Silk
A: 

At the least, you're missing using statements:

TcpListener recSock = new TcpListener(IPAddress.Loopback,  400);
recSock.Start();
using (TcpClient client = recSock.AcceptTcpClient())
{
    using (NetworkStream netStream = client.GetStream())
    {
        Byte[] data = new Byte[256];

        int i;

        while ((i = netStream.Read(data, 0, data.Length)) != 0)
        {
            string cmd = Encoding.ASCII.GetString(data, 0, i);
            Console.WriteLine(cmd);
            if (cmd == "R")
            {
                RestartScheduler();
            }
        }
    }

    client.Close();
}

and

using (TcpClient client = new TcpClient())
{
    client.Connect("VM-SCHEDULER", 400);
    using (NetworkStream netStream = client.GetStream())
    {
        Byte[] data = Encoding.ASCII.GetBytes("R");
        netStream.Write(data, 0, data.Length);
        netStream.Flush();
    }
    client.Close();
}
John Saunders