Search code examples
c#macostcpserverlistener

Repeating message, but shouldn't repeat this message in Task


problem See the problem in the picture. The Server starts a new Task for accepting the clients and then handles it in the function Handle(client), this all works fine, but it every time it repeats this one message "Client connecting...", but it shouldn't. Nothing else of the Task is called but this message. And the bool Pending() is false, so it shouldn't start another Task.

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace WebServer
{
    class WebServer
    {
        public static WebServer Server { get; private set; }

        private TcpListener _tcpListener = null;
        public CancellationTokenSource TokenSource { get; private set; }
        public CancellationToken Token { get; private set; }

        public int i = 0;

        static void Main(string[] args)
        {
            WebServer.Server = new WebServer();
        }

        WebServer()
        {
            IPAddress ipAddress;

            try
            {
                ipAddress = IPAddress.Parse("127.0.0.1");
            } catch(Exception e)
            {
                Console.WriteLine("Error while parsing ip address: " + e.Message);
                return;
            }

            _tcpListener = new TcpListener(ipAddress, 8080);
            _tcpListener.Start();

            TokenSource = new CancellationTokenSource();
            Token = TokenSource.Token;

            //Execute server
            Task.Run(() => Run());

            Console.ReadKey();
            TokenSource.Cancel();

            WaitHandle handle = Token.WaitHandle;
            handle.WaitOne();
        }

        private void Run()
        {
            Console.WriteLine("Server is runnning");
            while(!Token.IsCancellationRequested)
            {
                if(_tcpListener.Pending())
                {
                    Console.WriteLine("Pending: " + _tcpListener.Pending());
                    Task.Run(() => {
                        Console.WriteLine("Client connecting...");
                        TcpClient client = _tcpListener.AcceptTcpClient();

                        this.Handle(client);
                        return;
                    });
                }
            }
        }

        private void Handle(TcpClient client)
        {
            NetworkStream stream = client.GetStream();

            Console.WriteLine("Handling....");

            while(client.Connected)
            {
                if(stream.DataAvailable)
                {
                    Console.WriteLine("Start Reading...");
                    byte[] buffer = new byte[1024];
                    stream.Read(buffer, 0, 1024);
                    Console.WriteLine("Read: " + Encoding.ASCII.GetString(buffer));
                }

                client.Close();
            }
        }
    }
}

Client connecting shouldn't repeat every time, everything else works


Solution

  • Emrah Süngü's comments seem accurate and correct

    TcpClient client = _tcpListener.AcceptTcpClient(); // accept first
    Console.WriteLine("Client connecting...");
    
    // then start processing in your task
    Task.Run(() => this.Handle(client));
    

    It makes perfect sense when you think about it, you are in a while loop, and you are starting several tasks before the code to except the client actually runs.

    Disclaimer : This is totally untested and i am not responsible for and harm you cause to others or your self with this code :)