当我是多线程时,我只能从第一个线程发送一次消息,之后我无法从第一个线程发送消息

时间:2020-12-25 05:32:27

标签: c# multithreading

我正在开发一个具有单一服务器的多客户端聊天应用程序,但我遇到了一个问题。当我将单个客户端连接到服务器时,一切正常,但稍后当我连接 2 个或更多客户端时,我只能从第一个客户端发送一条消息,然后服务器停止接收来自第一个客户端的消息,而我仍然可以从第二个客户端顺利发送消息,没有任何问题

下面是我的服务器代码

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

namespace Server
{
    public partial class Form1 : Form
    {
        delegate void SetTextCallback(string text);
        TcpListener listener;
        TcpClient client;
        NetworkStream ns;
        Thread t;
        Thread main;
        string[] client_name = new string[50];
        int count;
        int count1 = 0;
        int indice = 0;

        public Form1()
        {
            InitializeComponent();
            button2.Enabled = false;
            main = new Thread(runserver);
        }

        public void runserver()
        {
            
            listener = new TcpListener(IPAddress.Loopback, 8888);
            listener.Start();
            while (true)
            {
                client = listener.AcceptTcpClient();
                ns = client.GetStream();
                //t = new Thread(connector);
                var childSocketThread = new Thread(() =>
                {
                    connector();
                });
                childSocketThread.Start();
                //t.Start();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            main.Start();
            button2.Enabled = true;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            button3.Enabled = false;
            String s = "Close";
            byte[] byteTime = Encoding.ASCII.GetBytes(s);
            ns.Write(byteTime, 0, byteTime.Length);
            client.GetStream().Close();
            client.Close();
            listener.Stop();
            button2.Enabled = false;
            button1.Enabled = true;
            textBox1.Text += "Server closed";
        }

        private void button3_Click(object sender, EventArgs e)
        {
            String s = textBox2.Text;
            textBox1.Text += "Server >> " + textBox2.Text + "\r\n";
            byte[] byteTime = Encoding.ASCII.GetBytes(s);
            ns.Write(byteTime, 0, byteTime.Length);
        }

        public void connector()
        {
            byte[] bytes = new byte[1024];
            
            while (true)
            {
                int bytesRead = ns.Read(bytes, 0, bytes.Length);
                string statement = Encoding.ASCII.GetString(bytes, 0, bytesRead);
                string temp = "";
                if (statement[0] == '#') 
                {
                    count++;
                    while (statement[count] != '#')
                    {
                        temp += statement[count];
                        count++;
                    }
                    client_name[indice] = temp;
                    indice++;
                    statement = statement.Remove(0, temp.Length+2);
                    this.text1(statement);
                    count = 0;
                }
                else
                    this.text1(statement);
            }
        }

        private void text1(string text)
        {
            int count2 = 1;
            string str = "";

            if (this.textBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(text1);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                if(text[0] == '*')
                {
                    while (text[count2] != '*')
                    {
                        str += text[count2];
                        count2++;
                    }
                    text = text.Remove(0, str.Length + 2);
                    this.textBox1.Text += str + " >> " + text + "\r\n";
                }
                else
                    this.textBox1.Text += client_name[indice - 1] + " >> " + text + "\r\n";

            }
        }

这是我的客户端代码

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

namespace Client
{
    public partial class Form1 : Form
    {
        delegate void SetTextCallback(string text);
        TcpClient client;
        NetworkStream ns;
        Thread t = null;
        string client_name;
        int port_num = 0;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            client_name = textBox4.Text;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            button2.Enabled = false;
            client = new TcpClient(textBox1.Text, port_num);
            ns = client.GetStream();
            String s = "#" + client_name + "#" +" Connected";
            byte[] byteTime = Encoding.ASCII.GetBytes(s);
            ns.Write(byteTime, 0, byteTime.Length);
            t = new Thread(Connector);
            t.Start();

        }

        private void button3_Click(object sender, EventArgs e)
        {
            String s = "*" + client_name + "*" + textBox3.Text;
            textBox2.Text += client_name +" >> " + textBox3.Text + "\r\n";
            byte[] byteTime = Encoding.ASCII.GetBytes(s);
            ns.Write(byteTime, 0, byteTime.Length);
        }

        public void Connector()
        {
            byte[] bytes = new byte[1024];
            while (true)
            {
                int bytesRead = ns.Read(bytes, 0, bytes.Length);
                string data = Encoding.ASCII.GetString(bytes, 0, bytesRead);
                if (data == "Close")
                {
                    button3.Enabled = false;
                    t.Abort();
                    client.GetStream().Close();
                    client.Close();
                }
                else
                    this.Text1(data);
            }
        }


        private void Text1(string text)
        {
            if (this.textBox2.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(Text1);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.textBox2.Text = this.textBox2.Text + "Server >> " + text + "\r\n";
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            string temp = textBox5.Text;
            port_num = int.Parse(temp);
        }
    }
}

请帮助我解决这个问题,我也是套接字编程的新手

1 个答案:

答案 0 :(得分:0)

服务器代码中的 TcpClient 和 NetworkStream 应保存在列表中以备将来使用。喜欢吹服务器代码

public partial class Form1 : Form
{
    delegate void SetTextCallback(string text);
    TcpListener listener;
    List<TcpClient> clients = new List<TcpClient>();
    List<NetworkStream> ns = new List<NetworkStream>();
    Thread t;
    Thread main;
    string[] client_name = new string[50];
    int count;
    int count1 = 0;
    int indice = 0;

    public Form1()
    {
        InitializeComponent();
        button2.Enabled = false;
        main = new Thread(runserver);            
    }

    public void runserver()
    {

        listener = new TcpListener(IPAddress.Loopback, 8888);
        listener.Start();
        while (true)
        {
            TcpClient tmpClient = listener.AcceptTcpClient();
            clients.Add(tmpClient);
            ns.Add(tmpClient.GetStream());
            //t = new Thread(connector);
            var childSocketThread = new Thread(() =>
            {
                connector(ns.Count - 1);
            });
            childSocketThread.Start();
            //t.Start();
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;
        main.Start();
        button2.Enabled = true;
    }

    private void button2_Click(object sender, EventArgs e)
    {
        button3.Enabled = false;
        String s = "Close";
        byte[] byteTime = Encoding.ASCII.GetBytes(s);
        for(int i = 0; i < ns.Count; i++)
        {
            ns[i].Write(byteTime, 0, byteTime.Length);
            clients[i].GetStream().Close();
            clients[i].Close();
        }
        listener.Stop();
        button2.Enabled = false;
        button1.Enabled = true;
        textBox1.Text += "Server closed";
        ns.Clear();
        clients.Clear();
    }

    private void button3_Click(object sender, EventArgs e)
    {
        String s = textBox2.Text;
        textBox1.Text += "Server >> " + textBox2.Text + "\r\n";
        byte[] byteTime = Encoding.ASCII.GetBytes(s);
        ns.ForEach(item => { item.Write(byteTime, 0, byteTime.Length); });
        //ns.Write(byteTime, 0, byteTime.Length);
    }

    public void connector(int index)
    {
        byte[] bytes = new byte[1024];

        while (true)
        {
            int bytesRead = ns[index].Read(bytes, 0, bytes.Length);
            string statement = Encoding.ASCII.GetString(bytes, 0, bytesRead);
            string temp = "";
            if (statement[0] == '#')
            {
                count++;
                while (statement[count] != '#')
                {
                    temp += statement[count];
                    count++;
                }
                client_name[indice] = temp;
                indice++;
                statement = statement.Remove(0, temp.Length + 2);
                this.text1(statement);
                count = 0;
            }
            else
                this.text1(statement);
        }
    }

    private void text1(string text)
    {
        int count2 = 1;
        string str = "";

        if (this.textBox1.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(text1);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            if (text[0] == '*')
            {
                while (text[count2] != '*')
                {
                    str += text[count2];
                    count2++;
                }
                text = text.Remove(0, str.Length + 2);
                this.textBox1.Text += str + " >> " + text + "\r\n";
            }
            else
                this.textBox1.Text += client_name[indice - 1] + " >> " + text + "\r\n";

        }
    }
}