I'm trying to train myself and i'm currently building a small Tcp server / client.
I have for the moment 3 small classes that connect, listen for clients and listen to messages. Here are the 3 classes :
public class ServersLauncher
{
    #region Main
    public static void Main(string[] args)
    {
        ServersLauncher sl = new ServersLauncher();
        Console.ReadLine();
        sl._udpServer?.Dispose();
        sl._tcpServer?.Dispose();
    }
    #endregion Main
    private UdpServer _udpServer;
    private TcpServer _tcpServer;
    private ServersLauncher()
    {
        _tcpServer = new TcpServer();
        Socket sc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 25004);
        sc.Bind(localEndPoint);
        IPEndPoint distantEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 25000);
        sc.Connect(distantEndPoint);
        while (!sc.Connected)
            Thread.Sleep(1000);
        byte[] buffer = Utility.ConvertMessage("Hell world !");
        sc.Send(buffer, buffer.Length, SocketFlags.None);
        sc.Close();
    }
}
On top is the server launcher, it launches the server, create the client and send a message.
public class TcpServer : IDisposable
{
    private readonly int _portTcp = 25000;
    private Socket _socket;
    private Thread _connectionsThread;
    private List<TcpClient> _clients;
    public TcpServer()
    {
        _clients = new List<TcpClient>();
        _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), _portTcp);
        _socket.Bind(endPoint);
        _connectionsThread = new Thread(new ThreadStart(ListenConnections));
        _connectionsThread.Start();
    }
    public void Dispose()
    {
        _connectionsThread.Abort();
        for(int i = 0; i < _clients.Count; i++)
        {
            _clients[i].Dispose();
        }
        _socket.Close();
    }
    private void ListenConnections()
    {
        _socket.Listen(100);
        while (true)
        {
            Socket clientSocket = _socket.Accept();
            _clients.Add(new TcpClient(clientSocket));
        }
    }
}
On top is the TcpServer that listen to the connections and create a client interface when one client connect.
public class TcpClient : IDisposable
{
    private Socket _client;
    private Thread _receiverThread;
    public TcpClient(Socket client)
    {
        _client = client;
        _receiverThread = new Thread(ReceiveMessage);
        _receiverThread.Start();
    }
    public void Dispose()
    {
        _receiverThread.Abort();
    }
    private void ReceiveMessage()
    {
        while (true)
        {
            byte[] buffer = new byte[1024];
            _client.Receive(buffer);
            Utility.DisplayThread("A message has been received : " + Encoding.ASCII.GetString(buffer).Trim());
        }
    }
}
And here is the TcpClient that store the socket client and listen for messages. Nothing that complicated but i have an issue with the reading of the message. Right now, if i launch the program, the client connect but then... non stop messages ! I receive one "Hell world" then empty messages. I read the documentation of the Receive method for the Socket and it seems that it should block and wait for a message to pursue is routine. Do i do something wrong somewhere ? Do i need to flush the stream from the client before disconnecting ? Thanks for helping !