title: Multi client chat in C# using form and TCP Protocol (not UDP)
body: <p>I have tried 2 of how to make multi client, which is multi thread and asynchronous  server. Both didn't work for me. The multi thread can make client send broadcast to all client, but some of them didn't receive the broadcasted data. While the asynchronous server cannot make the client connect too long. I don't know whether it's my code that's wrong or what. Please help me based on my latest working code. </p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using System.Threading;
  using System.Net;
  using System.Net.Sockets;
  using System.IO;
  
  namespace Server
  {
      public partial class Form1 : Form
      {
          private TcpClient client;
          public StreamReader STR;
          public StreamWriter STW;
          public string receive;
          public String text_to_send;
  
          public Form1()
          {
              InitializeComponent();
  
              IPAddress[] localIP = Dns.GetHostAddresses(Dns.GetHostName());      //Using the PC's IP
              foreach (IPAddress address in localIP) {
                  if (address.AddressFamily == AddressFamily.InterNetwork) {
                      textBox5.Text = address.ToString();
                  }
              }
          }
  
          private void Form1_Load(object sender, EventArgs e)
          {
  
          }
  
          private void button2_Click(object sender, EventArgs e) //Button to start the server
          {
              TcpListener listener = new TcpListener(IPAddress.Any, int.Parse(textBox6.Text));
              listener.Start();
              client = listener.AcceptTcpClient();
              STR = new StreamReader(client.GetStream());
              STW = new StreamWriter(client.GetStream());
              STW.AutoFlush = true;
  
              backgroundWorker1.RunWorkerAsync(); //Start receiving data in the background
              backgroundWorker2.WorkerSupportsCancellation = true; //Cancel the active thread
          }
  
          private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) //Receiving data
          {
              while(client.Connected)
              {
                  try
                  {
                      receive = STR.ReadLine();
                      this.textBox2.Invoke(new MethodInvoker(delegate() { textBox2.AppendText("You : " + receive + "\n   Received : " + receive.Length.ToString() + " byte. \n"); }));
                      receive = "";
                  }
                  catch(Exception x)
                  {
                      MessageBox.Show(x.Message.ToString());
  
                  }
              }
          }
  
          private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) //Sending data
          {
              if (client.Connected)
              {
                  STW.WriteLine(text_to_send);
                  this.textBox2.Invoke(new MethodInvoker(delegate() { textBox2.AppendText("Me : " + text_to_send + "\n  Sent : " + text_to_send.Length.ToString() + " byte \n"); }));//Text that will appeared on the screen after we enter the text that we type
              }
              else
              {
                  MessageBox.Show("Send Failed!");
              }
              backgroundWorker2.CancelAsync();
          }
  
          private void button3_Click(object sender, EventArgs e) //Connected as client
          {
              client = new TcpClient();
              IPEndPoint IP_End = new IPEndPoint(IPAddress.Parse(textBox3.Text), int.Parse(textBox4.Text));
  
              try
              {
                  client.Connect(IP_End);
                  if (client.Connected) {
                      textBox2.AppendText("Connected to server" + "\n");
                      STW = new StreamWriter(client.GetStream());
                      STR = new StreamReader(client.GetStream());
                      STW.AutoFlush = true;
  
                      backgroundWorker1.RunWorkerAsync(); //Start receiving data in the background
                      backgroundWorker2.WorkerSupportsCancellation = true; //Cancel the active thread
                  }
              }
              catch(Exception x)
              {
                  MessageBox.Show(x.Message.ToString());
              }
  
          }
  
          private void button1_Click(object sender, EventArgs e)  //Send button
          {
              if (textBox1.Text != "")
              {
                  text_to_send = textBox1.Text;
                  backgroundWorker2.RunWorkerAsync();
              }
              textBox1.Text = "";
          }
  
          private void label1_Click(object sender, EventArgs e)
          {
  
          }
      }
  }
  </code></pre>
  
  <p>N.B : Just translated the comment into English</p>