【问题标题】:multi threading issue in C# client/server chat applicationC# 客户端/服务器聊天应用程序中的多线程问题
【发布时间】:2016-03-15 22:10:17
【问题描述】:

我有一个使用 C# 的 TCP 服务器/客户端聊天程序。该服务器接收来自客户的消息并重新发送到目标。

当客户端连接到服务器时,服务器会为他创建一个新线程。

我的问题是服务器只接收到客户的一条消息没有收到他的任何新消息。

当我进行调试时,我注意到服务器收到消息并挂在客户端线程中但没有再次运行。

服务器代码:

namespace server
{
public partial class Form1 : Form
{
    private ArrayList alSockets;
    private delegate void UpdateLogCallback(string strMessage);


    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

        IPHostEntry IPHost = Dns.GetHostByName(Dns.GetHostName());
        textBox1.Text = "my ip is " + IPHost.AddressList[0].ToString();
        alSockets = new ArrayList();
        Thread thdListener = new Thread(new ThreadStart(listenerThread));
        thdListener.Name = "thdListener";
        
        thdListener.Start();

    }
    public void listenerThread()
    {
        TcpListener tcpc = new TcpListener(IPAddress.Any,6666);
        tcpc.Start();

        while (true)
        {
            Socket HndSoc = tcpc.AcceptSocket();
            if (HndSoc.Connected)
            {
                string str2 = "\n" + HndSoc.RemoteEndPoint.ToString() + " connected";
                this.Invoke(new UpdateLogCallback(this.update2),new object[] {str2});

                lock (this)
                {
                    alSockets.Add(HndSoc);

                }
                ThreadStart thdstHandler = new ThreadStart(handlerThread);
                Thread thdHandler = new Thread(thdstHandler);
                thdHandler.Name = "thdHandler";
                thdHandler.Start();
                
             }
            else if(!HndSoc.Connected)
            {
                string str2 = "\n" + HndSoc.RemoteEndPoint.ToString() + " desconnected";
                this.Invoke(new UpdateLogCallback(this.update2), new object[] { str2 });

            }

            }
        }
    public void handlerThread()
    {
        byte [] rx = new byte [1024];
        Socket hanso = (Socket) alSockets[alSockets.Count-1];
       NetworkStream ns = new NetworkStream(hanso);
       // NetworkStream  ns = hanso. 
        ns.Read(rx,0,rx.Length);
   //     textBox1.Text = "\n";
     //   textBox1.Text =  Encoding.ASCII.GetString(rx);
        string str = Encoding.ASCII.GetString(rx);
       // update(str);
        this.Invoke(new UpdateLogCallback(this.update), new object[] { str });
       // ns.Close();
       // hanso = null;
        rx = new byte[1024];
        ns.Read(rx, 0, rx.Length);
        
    }

如果需要,这是客户端代码:

namespace simple_clint
{
public partial class Form1 : Form
{
    byte[] tx = new byte[1024];
  //  IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"),6666);

    TcpClient tcp1 = new TcpClient("127.0.0.1", 6666);


    public Form1()
    {
        InitializeComponent();
    }

    private void send_Click(object sender, EventArgs e)
    {
        tx = Encoding.ASCII.GetBytes(textBox1.Text);
        try
        {
            NetworkStream ns = tcp1.GetStream();
            ns.Write(tx, 0, tx.Length);
          //  ns.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }

    private void Form1_Load(object sender, EventArgs e)
    {
        try
        {
           
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}
}

【问题讨论】:

  • 看一眼,似乎需要在handlerThread()中添加一个循环。
  • 非常感谢您的帮助..它有效。循环应该在这一行之前: NetworkStream ns = new NetworkStream(hanso);我应该删除最后两行
  • 另外,您的服务器代码不是线程安全的。您不能在没有同步的情况下从多个线程中修改和读取ArrayList。您不能仅仅假设当处理程序线程开始读取套接字时,正确的仍然是列表中的最后一个。还有,你为什么用ArrayList?您是否坚持使用 .NET 1.1 或其他内容?只需使用List<Socket>。并将接受的套接字直接传递给处理程序线程方法。异步 I/O 也可能是比多线程更好的选择 - 无需浪费线程无所事事。
  • 谢谢你的笔记我希望使用异步I/O但是没有看到很好的参考,如果你有好的书或文章希望给我。

标签: c# multithreading tcplistener


【解决方案1】:

感谢 kajacx。我需要将循环添加到 handlerThread() 新代码:

public void handlerThread()
    {

            byte[] rx = new byte[1024];
            Socket hanso = (Socket)alSockets[alSockets.Count - 1];
            while (true)
            {
            NetworkStream ns = new NetworkStream(hanso);
            ns.Read(rx, 0, rx.Length);
            string str = Encoding.ASCII.GetString(rx);
            this.Invoke(new UpdateLogCallback(this.update), new object[] { str });

        }

    }

然后我删除最后两行

【讨论】:

    猜你喜欢
    • 2014-10-21
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 2015-02-17
    • 2013-04-09
    • 2011-06-18
    相关资源
    最近更新 更多