C#客户端/服务器聊天应用程序,无法重新连接或重新创建套接字

时间:2018-02-13 16:35:00

标签: c# sockets

我有一个基于指南构建的简单客户端/服务器聊天应用程序。在客户端应用程序中,有一个方法可以启动连接,然后是另一个正在寻找来自服务器的新消息的方法(在线程下运行)。这可以按预期工作,但是如果与服务器实例的连接失败(例如,如果我终止服务器),则客户端无法再重新连接,因为该对象

    TcpClient clientSocket = new TcpClient();

是全局声明的,不能重新用于新的连接尝试,因为套接字是一个用途。如果它尝试重用它,我会得到一个例外,即远程主机已经关闭了这个套接字上的连接。

为了解决这个问题,我知道每次运行连接方法时都需要创建 clientSocket 对象的新实例,以避免在连接丢失事件后重新启动客户端。通过在连接方法而不是全局创建 clientSocket ,它工作正常,我可以通过在连接丢失后再次运行该方法重新连接,但是,我无法传递此特定对象实例(因为它是在我的方法而不是全局创建的 getMessage()监听器方法,所以它不能通过这个套接字进行交互。

根据我的理解,有两种可能的解决方案:

  • 我反复重复使用相同的 clientSocket 实例 再次,通过断开连接并重新连接它。这不行,就像我一样 似乎没有能够正确断开它,我不断得到 我不能重新连接到活动套接字的例外(在...中 现实,已经断开,因为服务器被杀死了)。我可以 .Close()它,但是无法创建新实例。

  • 或者我每次创建一个新的TcpClient clientSocket 实例 尝试连接如上所述,这似乎是方式 go,但我不能让我的getMessage方法看到并使用这个特定的 实例。如果我显然在getMessage中重新创建实例 因为该实例未连接而无法正常工作。

简而言之,我需要我的方法与在不同方法范围内创建的特定对象实例进行交互。或者允许我在代码中重用/重新创建相同套接字的任何其他解决方案。如果代码不清楚,我很乐意回答任何问题。

完整的客户代码:

    public partial class Form1 : Form
    {  
        TcpClient clientSocket = new TcpClient(); // im declaring this globally here, this way both methods can see it but i cannot reuse it after a connection loss

        NetworkStream serverStream = default(NetworkStream);

        string readData = null;
        bool connect = true;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {                
            byte[] outStream = Encoding.ASCII.GetBytes(textBox2.Text + "$");
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();
        }

        //This method initiates the connection
        public void button2_Click(object sender, EventArgs e)
        {    
            // i COULD create the TcpClient clientSocket instance here instead, but this way getMessage() will not be able to see it
            connect = true;

            try {

                string ip = ipBox.Text;
                int port = Convert.ToInt32(portBox.Text);
                readData = "Connected";

                clientSocket.Connect(ip, port);
                serverStream = clientSocket.GetStream();

                byte[] outStream = Encoding.ASCII.GetBytes(textBox3.Text + "$");
                serverStream.Write(outStream, 0, outStream.Length);
                serverStream.Flush();
                msg();

                Thread ctThread = new Thread(getMessage);
                ctThread.Start();
            }    
            catch
            {
                MessageBox.Show("Connection failed, cannot reach host");    
            }
            }

        // This method is being ran under a thread to keep looking for messages
        private void getMessage()
        {
            while (connect == true)
            {
                serverStream = clientSocket.GetStream();
                int buffSize = 0;
                byte[] inStream = new byte[10025];
                buffSize = clientSocket.ReceiveBufferSize;

                try
                {
                    serverStream.Read(inStream, 0, buffSize);
                }
                catch
                {    
                    MessageBox.Show("Connection lost, server stopped responding");
                    connect = false;
                }

                string returndata = Encoding.ASCII.GetString(inStream);
                readData = "" + returndata;
                msg();
            }    
        }
        private void msg()
        {
            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker(msg));
            else
                textBox1.Text = textBox1.Text + Environment.NewLine + " >> " + readData;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ipBox.Text = "xx.xx.xx.xx";
            portBox.Text = "8888";
            textBox3.Text = Environment.UserDomainName + "//" + Environment.UserName;
        }
    }

感谢任何帮助,我经历了无数的问题和文章,但无法找到答案。

1 个答案:

答案 0 :(得分:0)

我设法找到了解决方案:

How to pass parameters to ThreadStart method in Thread?

我能够使用第一个答案将我的实例引用传递给新方法,现在一切正常。