tcp server chat [closed]

-3

This is the following I have a tcp server for chat. every time I start the server and then close the form, the program gives an error because it is in an infinite loop in this part of the code:

while (Connected)
{
    Sendtxtbox.Enabled = true;
    // Mostra a mensagem na TextBox.
    try
    {

        this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { 
            srReceiver.ReadLine() 
        });
    }
    catch
    { }
}

How can I break the loop when the tcp server closes?

All code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace Random
{
    public partial class Chat : Form
    {
        private delegate void UpdateStatusCallback(string strMessage);
        private string UserName = "Desconhecido";
        private StreamWriter swSender;
        private StreamReader srReceiver;
        private TcpClient tcpServer;
        private delegate void UpdateLogCallback(string strMessage);
        private delegate void CloseConnectionCallback(string strReason);
        private Thread thrMessaging;
        private IPAddress ipAddr;
        private bool Connected;
        private ChatServer mainServer;

        public Chat()
        {
            InitializeComponent();

        }
        private void InitializeConnection()
        {
            btnLiga.Enabled = false;
            // Parse the server's IP address out of the TextBox
            IPAddress ipAddr = IPAddress.Parse(Iptxtbox.Text);
            // Create a new instance of the ChatServer object
            mainServer = new ChatServer(ipAddr);


            // Hook the StatusChanged event handler to mainServer_StatusChanged
            //ChatServer.StatusChanged += new StatusChangedEventHandler(mainServer_StatusChanged);

            // Start listening for connections
            mainServer.StartListening();
            // Show that we started to listen for connections
            Logtxtbox.AppendText("Conectado...\r\n");
            // Analise o IP da TextBox para um IPAddress.
            ipAddr = IPAddress.Parse(Iptxtbox.Text);
            // Começa uma nova começao TCP para o chat servidor.
            tcpServer = new TcpClient();
            tcpServer.Connect(ipAddr, 1177);
            Connected = true;
            UserName = Usertxtbox.Text;
            Iptxtbox.Enabled = false;
            Usertxtbox.Enabled = false;
            Logtxtbox.Enabled = true;
            Sendbtn.Enabled = true;
            btnLiga.Text = "Disconnectar";
            // Envia o username pretendido para o server.
            swSender = new StreamWriter(tcpServer.GetStream());
            swSender.WriteLine(Usertxtbox.Text);
            swSender.Flush();
            // Começa uma tarefa para receber mensagens e adicionar na comunicaçao.
            thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
            thrMessaging.Start();

        }

        private void btnLiga_Click(object sender, EventArgs e)
        {
            if (Usertxtbox.Text.Length == 0)
                MessageBox.Show("Introduza um nick valido.", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
            else
            {
                // Se nao estivermos conectados mas á espera de conectar.
                if (Connected == false)
                {
                    // Conecta.
                    InitializeConnection();
                }
                else // Se estivermos conectados, disconecta.
                {
                    CloseConnection("Disconectado.");
                }
            }

        }
        //public void mainServer_StatusChanged(object sender, StatusChangedEventArgs e)
        //{
        //    // Call the method that updates the form
        //    this.Invoke(new UpdateStatusCallback(this.UpdateStatus), new object[] { e.EventMessage });
        //}
        ////private void UpdateStatus(string strMessage)
        ////{
        ////    // Updates the log with the message
        ////    Logtxtbox.AppendText(strMessage + "\r\n");
        ////}
        private void SendMessage()
        {
            if (Sendtxtbox.Lines.Length >= 1)
            {
                swSender.WriteLine(Sendtxtbox.Text);
                swSender.Flush();
                Sendtxtbox.Lines = null;
            }
            Sendtxtbox.Text = "";
        }


        private void Sendbtn_Click(object sender, EventArgs e)
        {
            SendMessage();
        }
        private void ReceiveMessages()
        {
            // Recebe a resposta do servidor.
            srReceiver = new StreamReader(tcpServer.GetStream());
            string ConResponse = srReceiver.ReadLine();
            // Se o primeiro caracter da resposta for 1, a coneçao é feita com sucesso.
            if (ConResponse[0] == '1')
            {
                // Actualiza a form para dizer que nao estamos conectados agora.
                this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Conectado! :D" });
            }
            else
            {
                string Reason = "Nao conectado: ";
                Reason += ConResponse.Substring(2, ConResponse.Length - 2);
                // Actualiza a form com a razao do qual nos nao poderiamos estar conectados.
                this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
                // Exit the method
                return;
            }
            // Enquanto nos estamos conectados, le as linhas do servidor.
            while (Connected)
            {
                Sendtxtbox.Enabled = true;
                // Mostra a mensagem na TextBox.
                try
                {

                    this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
                }
                catch
                { }
            }
        }
        private void UpdateLog(string strMessage)
        {

            Logtxtbox.AppendText(strMessage + "\r\n");
        }
        private void CloseConnection(string Reason)
        {

            // Mostra o porque da coneçao ter fechado.
            Logtxtbox.AppendText(Reason + "\r\n");
            // Activa e desactiva os controlos apropriados da form.
            Iptxtbox.Enabled = true;
            Usertxtbox.Enabled = true;
            Sendtxtbox.Enabled = false;
            Sendbtn.Enabled = false;
            // Fecha os objectos.
            Connected = false;
            swSender.Close();
            srReceiver.Close();
            tcpServer.Close();
            //mainServer.CloseListening();
            btnLiga.Text = "Conectar";
        }

        private void Chat_FormClosed(object sender, FormClosedEventArgs e)
        {

           // CloseConnection("Disconectado.");
            Connection con = new Connection(tcpServer);
            con.CloseConnection();
            this.Hide();
        }

    }
}

This is the second part:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

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

namespace Random
{
    // Holds the arguments for the StatusChanged event
    public class StatusChangedEventArgs : EventArgs
    {
        // The argument we're interested in is a message describing the event
        private string EventMsg;

        // Property for retrieving and setting the event message
        public string EventMessage
        {
            get
            {
                return EventMsg;
            }
            set
            {
                EventMsg = value;
            }
        }

        // Constructor for setting the event message
        public StatusChangedEventArgs(string strEventMsg)
        {
            EventMsg = strEventMsg;
        }
    }

    // This delegate is needed to specify the parameters we're passing with our event
    public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);

    class ChatServer
    {
        // This hash table stores users and connections (browsable by user)
        public static Hashtable htUsers = new Hashtable(30); // 30 users at one time limit
        // This hash table stores connections and users (browsable by connection)
        public static Hashtable htConnections = new Hashtable(30); // 30 users at one time limit
        // Will store the IP address passed to it
        private IPAddress ipAddress;
        private TcpClient tcpClient;
        // The event and its argument will notify the form when a user has connected, disconnected, send message, etc.
        public static event StatusChangedEventHandler StatusChanged;
        private static StatusChangedEventArgs e;

        // The constructor sets the IP address to the one retrieved by the instantiating object
        public ChatServer(IPAddress address)
        {
            ipAddress = address;
        }

        // The thread that will hold the connection listener
        private Thread thrListener;

        // The TCP object that listens for connections
        private TcpListener tlsClient;

        // Will tell the while loop to keep monitoring for connections
        bool ServRunning = false;

        // Add the user to the hash tables
        public static void AddUser(TcpClient tcpUser, string strUsername)
        {
            // First add the username and associated connection to both hash tables
            ChatServer.htUsers.Add(strUsername, tcpUser);
            ChatServer.htConnections.Add(tcpUser, strUsername);

            // Tell of the new connection to all other users and to the server form
            SendAdminMessage(htConnections[tcpUser] + " has joined us");
        }

        // Remove the user from the hash tables
        public static void RemoveUser(TcpClient tcpUser)
        {
            // If the user is there
            if (htConnections[tcpUser] != null)
            {
                // First show the information and tell the other users about the disconnection
                SendAdminMessage(htConnections[tcpUser] + " has left us");

                // Remove the user from the hash table
                ChatServer.htUsers.Remove(ChatServer.htConnections[tcpUser]);
                ChatServer.htConnections.Remove(tcpUser);
            }
        }

        // This is called when we want to raise the StatusChanged event
        public static void OnStatusChanged(StatusChangedEventArgs e)
        {
            StatusChangedEventHandler statusHandler = StatusChanged;
            if (statusHandler != null)
            {
                // Invoke the delegate
                statusHandler(null, e);
            }
        }

        // Send administrative messages
        public static void SendAdminMessage(string Message)
        {
            StreamWriter swSenderSender;

            // First of all, show in our application who says what
            e = new StatusChangedEventArgs("Administrator: " + Message);
            OnStatusChanged(e);

            // Create an array of TCP clients, the size of the number of users we have
            TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count];
            // Copy the TcpClient objects into the array
            ChatServer.htUsers.Values.CopyTo(tcpClients, 0);
            // Loop through the list of TCP clients
            for (int i = 0; i < tcpClients.Length; i++)
            {
                // Try sending a message to each
                try
                {
                    // If the message is blank or the connection is null, break out
                    if (Message.Trim() == "" || tcpClients[i] == null)
                    {
                        continue;
                    }
                    // Send the message to the current user in the loop
                    swSenderSender = new StreamWriter(tcpClients[i].GetStream());
                    swSenderSender.WriteLine("Administrator: " + Message);
                    swSenderSender.Flush();
                    swSenderSender = null;
                }
                catch // If there was a problem, the user is not there anymore, remove him
                {
                    RemoveUser(tcpClients[i]);
                }
            }
        }

        // Send messages from one user to all the others
        public static void SendMessage(string From, string Message)
        {
            StreamWriter swSenderSender;

            // First of all, show in our application who says what
            e = new StatusChangedEventArgs(From + " says: " + Message);
            OnStatusChanged(e);

            // Create an array of TCP clients, the size of the number of users we have
            TcpClient[] tcpClients = new TcpClient[ChatServer.htUsers.Count];
            // Copy the TcpClient objects into the array
            ChatServer.htUsers.Values.CopyTo(tcpClients, 0);
            // Loop through the list of TCP clients
            for (int i = 0; i < tcpClients.Length; i++)
            {
                // Try sending a message to each
                try
                {
                    // If the message is blank or the connection is null, break out
                    if (Message.Trim() == "" || tcpClients[i] == null)
                    {
                        continue;
                    }
                    // Send the message to the current user in the loop
                    swSenderSender = new StreamWriter(tcpClients[i].GetStream());
                    swSenderSender.WriteLine(From + "  diz: " + Message);
                    swSenderSender.Flush();
                    swSenderSender = null;
                }
                catch // If there was a problem, the user is not there anymore, remove him
                {
                    RemoveUser(tcpClients[i]);
                }
            }
        }

        public void StartListening()
        {

            // Get the IP of the first network device, however this can prove unreliable on certain configurations
            IPAddress ipaLocal = ipAddress;

            // Create the TCP listener object using the IP of the server and the specified port
            tlsClient = new TcpListener(1177);

            // Start the TCP listener and listen for connections
            tlsClient.Start();


            // The while loop will check for true in this before checking for connections
            ServRunning = true;

            // Start the new tread that hosts the listener
            thrListener = new Thread(KeepListening);
            thrListener.Start();
        }

        public void CloseListening()
        {
            //thrListener.Abort();
            tlsClient.Stop();
            ServRunning = false;
        }



        private void KeepListening()
        {
            // While the server is running
            while (ServRunning == true)
            {
                // Accept a pending connection
                tcpClient = tlsClient.AcceptTcpClient();
                // Create a new instance of Connection
                Connection newConnection = new Connection(tcpClient);
            }
        }
    }

    // This class handels connections; there will be as many instances of it as there will be connected users
    public class Connection
    {
        TcpClient tcpClient;
        // The thread that will send information to the client
        private Thread thrSender;
        private StreamReader srReceiver;
        private StreamWriter swSender;
        private string currUser;
        private string strResponse;

        // The constructor of the class takes in a TCP connection
        public Connection(TcpClient tcpCon)
        {
            tcpClient = tcpCon;
            // The thread that accepts the client and awaits messages
            thrSender = new Thread(AcceptClient);
            // The thread calls the AcceptClient() method
            thrSender.Start();
        }

        public void CloseConnection()
        {
            // Close the currently open objects
            tcpClient.Close();
            srReceiver.Close();
            swSender.Close();
        }

        // Occures when a new client is accepted
        private void AcceptClient()
        {
            srReceiver = new System.IO.StreamReader(tcpClient.GetStream());
            swSender = new System.IO.StreamWriter(tcpClient.GetStream());

            // Read the account information from the client
            currUser = srReceiver.ReadLine();

            // We got a response from the client
            if (currUser != "")
            {
                // Store the user name in the hash table
                if (ChatServer.htUsers.Contains(currUser) == true)
                {
                    // 0 means not connected
                    swSender.WriteLine("0|This username already exists.");
                    swSender.Flush();
                    CloseConnection();
                    return;
                }
                else if (currUser == "Administrator")
                {
                    // 0 means not connected
                    swSender.WriteLine("0|This username is reserved.");
                    swSender.Flush();
                    CloseConnection();
                    return;
                }
                else
                {
                    // 1 means connected successfully
                    swSender.WriteLine("1");
                    swSender.Flush();

                    // Add the user to the hash tables and start listening for messages from him
                    ChatServer.AddUser(tcpClient, currUser);
                }
            }
            else
            {
                CloseConnection();
                return;
            }

            try
            {
                // Keep waiting for a message from the user
                while ((strResponse = srReceiver.ReadLine()) != "")
                {
                    // If it's invalid, remove the user
                    if (strResponse == null)
                    {
                        ChatServer.RemoveUser(tcpClient);
                    }
                    else
                    {
                        // Otherwise send the message to all the other users
                        ChatServer.SendMessage(currUser, strResponse);
                    }
                }
            }
            catch
            {
                // If anything went wrong with this user, disconnect him
                ChatServer.RemoveUser(tcpClient);
            }
        }
    }
}
    
asked by anonymous 11.08.2016 / 17:29

1 answer

1

Problem resolved by a break; here

private void KeepListening()
{
    // While the server is running
    while (ServRunning == true)
    {
        // Accept a pending connection
        tcpClient = tlsClient.AcceptTcpClient();
        // Create a new instance of Connection
        Connection newConnection = new Connection(tcpClient);
        break;
    }
}

and here

private void Chat_FormClosed(object sender, FormClosedEventArgs e)
{

    // CloseConnection("Disconectado.");
    Connection con = new Connection(tcpServer);
    con.CloseConnection();
    this.Hide();
}

change this

   // CloseConnection("Disconectado.");
    Connection con = new Connection(tcpServer);
    con.CloseConnection();

This is why CloseConnection("Disconectado.");

    
12.08.2016 / 11:32