Search code examples
c#tcpclient-servertcpclient

TcpClient: Operation not allowed on non-connected Sockets - C# 4.5


Why is the following code giving the following exception?

The operation not allowed on non-connected sockets.

This link says that:

You gotta Connect() before you can get the NetworkStream.

The documentation is usually pretty good for this kinda stuff. Under Exceptions in the help for GetStream, you'll see:

InvalidOperationException: The TcpClient is not connected to a remote host.

Here, my client is doing the same.

So, what is going wrong?

enter image description here

Client code:

using System;
using System.Net.Sockets;
using System.IO;

namespace WhoIsClientNamespace
{
    public class WhoIsClient
    {
        static void Main()
        {
            Console.Title = "Client";
            string kbInput;
            try
            {
                TcpClient client = new TcpClient();
                client.Connect("localHost", 43);
                Console.WriteLine("Client started...");
                Console.WriteLine("Enter command to the server!");
                Console.WriteLine(" # ");

                while (true)
                {
                    kbInput = Console.ReadLine();
                    Console.WriteLine(kbInput);

                    if ("exit" == kbInput)
                    {
                        Console.WriteLine("while loop exited!");
                        break;
                    }

                    string[] args = kbInput.Split(' ');

                    if (args.Length < 1)
                    {
                        Console.WriteLine("Provide more than one Args");
                    }
                    else if (args.Length == 1)
                    {
                        StreamWriter sw = new StreamWriter(client.GetStream());
                        StreamReader sr = new StreamReader(client.GetStream());
                        string str = kbInput;
                        sw.WriteLine(kbInput);
                        sw.Flush();
                        Console.WriteLine(kbInput[0] + " is " + sr.ReadToEnd());
                        return;
                    }
                    else if (args.Length > 1)
                    {
                        StreamWriter sw = new StreamWriter(client.GetStream());
                        StreamReader sr = new StreamReader(client.GetStream());
                        string str = kbInput;
                        sw.WriteLine(str);
                        sw.Flush();
                        //Console.WriteLine(kbInput[0] + " location changed to be " + args[1]);
                        sw.Close();
                    }
                    else
                    {
                        Console.WriteLine("Invalid args ");
                    }
                }                
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.WriteLine("Client exits!");
        }
    }
}

Server code:

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections.Generic;

namespace WhoIsServerNamespace
{
    public class WhoIsServer
    {
        static Dictionary<string, string> 
            _locationsDictionary = new Dictionary<String, String>();
        static void Main(string[] args)
        {
            Console.Title = "Server";
            runServer();
        }
        static void runServer()
        {
            TcpListener listener;
            Socket connection;
            NetworkStream socketStream;
            try
            {
                listener = new TcpListener(IPAddress.Any, 43);
                listener.Start();

                Console.WriteLine("server started listening");

                while (true)
                {
                    connection = listener.AcceptSocket();
                    socketStream = new NetworkStream(connection);
                    Console.WriteLine("Connection Received");
                    doRequest(socketStream);
                    socketStream.Close();
                    connection.Close();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception:" + e.ToString());
            }
        }

        static void doRequest(NetworkStream socketStream)
        {
            try
            {
                StreamWriter sw = new StreamWriter(socketStream);
                StreamReader sr = new StreamReader(socketStream);
                String strClientInput = sr.ReadLine();
                Console.WriteLine("Respond Received:" + strClientInput);
                String[] clientInputsSplitted = strClientInput.Split(new char[] { ' ' }, 2);
                String name;
                String location;

                if (clientInputsSplitted.Length < 1)
                {
                    Console.WriteLine("Too little words was inputted");
                }
                else if (clientInputsSplitted.Length == 1)
                {/* when we receive only one command-string from client,
                    that is considered as the name of the server.
                    So, the server returns its corresponding location. */
                    name = clientInputsSplitted[0];//obtain the name from the client-command-string.
                    if (_locationsDictionary.ContainsKey(name))//Is the [name] in the dictionary?
                    {
                        Console.WriteLine(name + "'s location is :"+ _locationsDictionary[name]);
                        sw.WriteLine(_locationsDictionary[name]);//return location to the client.
                    }
                    else
                    {
                        Console.WriteLine("Error: [name] not found in the dictionary");
                        sw.WriteLine("Error: [name] not found in the dictionary");
                    }
                    sw.Flush();
                }
                else if (clientInputsSplitted.Length == 2)
                {/* when we receive two command-string from client,
                    that is considered as the (name, location) pair of the server.
                    So, the server returns its corresponding location. */
                    name = clientInputsSplitted[0];
                    location = clientInputsSplitted[1];

                    if (_locationsDictionary.ContainsKey(name))
                    {
                        _locationsDictionary[name] = location;
                        Console.WriteLine("(" + name + "," + location + ") updated");
                        sw.WriteLine("("+name +","+ location +") updated");
                    }
                    else
                    {
                        _locationsDictionary.Add(name, location);
                        Console.WriteLine("(" + name + "," + location + ") added");
                        sw.WriteLine("(" + name + "," + location + ") added");
                    }
                    sw.Flush();
                }

                if (strClientInput.Contains("-h0"))
                {
                    Console.WriteLine("Is                ok");
                    sw.WriteLine("Is ok");
                }
                else if (strClientInput.Contains("-h9"))
                {
                    Console.WriteLine("Hey you're progressing");
                    sw.WriteLine("Hey you're progressing");
                }
                else if (strClientInput.Contains("-h1"))
                {
                    Console.WriteLine("We're Done");
                    sw.WriteLine("We're Done");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Something went wrong");
                Console.WriteLine(e.Message);
            }
        }
    }
}

Solution

  • Looks like your server side implementation close the socket after doRequest, so for client side you need to make new instance of TcpClient for each input. Or rewrite server side code to keep socket opened.