【问题标题】:Multi-Client Server Behaves Strangely多客户端服务器行为异常
【发布时间】:2014-12-13 18:13:48
【问题描述】:

下面是一段代码。我正在尝试分别处理上游和下游。但不幸的是,handleUpStream() 永远不会在handleDownStream 之后发生。

如果我删除handleDownStream,handleupstream 一切都会好起来的。我在 handleDownStream 中缺少一些东西,我不知道是什么。

    public void run()
    {
        while (running)
        {
            if (ClientPool == null)
                continue;
            foreach (Client c in ClientPool)
            {
                NetworkStream networkStream = c.getTcpClient().GetStream();
                handleDownStream(c, networkStream);
                handleUpstream(c, networkStream);
            }
        }
    }

    public void handleDownStream(Client c, NetworkStream networkstream)
    {
        try
        {
            networkstream.Read(bytesFrom, 0, (int)c.getTcpClient().ReceiveBufferSize);
            dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
            Console.WriteLine("Message From: " + c.getClientIp() + " : " + dataFromClient);
            dataFromClient = null;
            bytesFrom = new byte[10025];
        }
        catch (Exception e)
        { 
            // I tried to see if there was some sort of exception here that was a silent killer. 
            Console.WriteLine(e.ToString());
            return;
        }
    }

    public void handleUpstream(Client c, NetworkStream networkstream)
    {
        // The below never happens.
        Console.WriteLine("this lol");
        if (c.getTimeSinceLastMessage() > 30000 && c.getPinged())
        {
            Console.WriteLine("Removing Client From Pool, " + c.getClientIp());
            removeClientFromPool(c);
            return;
        }
        if (c.getTimeSinceLastMessage() > 15000 && c.getPinged() == false)
        {
            Console.WriteLine("Sending ping to Client, " + c.getClientIp());
            c.switchPinged();
            bytesToSend = Encoding.ASCII.GetBytes("ping");
            networkstream.Write(bytesToSend, 0, bytesToSend.Length);
            networkstream.Flush();
            bytesToSend = null;
        }
    }

【问题讨论】:

  • 如果您的代码从未进入某个位置,则意味着它在该位置之前停止。使用调试器单步执行此代码以找出位置。
  • 您是否尝试逐步检查以确保 networkstream.Read 不会以某种方式阻碍您?另外,在阅读之前可能需要检查CanRead (msdn.microsoft.com/en-us/library/…)。

标签: c# multithreading sockets


【解决方案1】:

这太尴尬了……

除了检查它之外,您还需要检查是否有数据可供阅读......对于像我这样的新手或忘记检查的人来说,这里是更新的代码。很明显,如果您调用 networkstream.read() 它会等待一条消息(它与线程的同步器)。

这是修改后的工作代码,供需要查看发生了什么的人使用。

public void run()
    {
        while (running)
        {
            if (ClientPool == null)
                continue;
            foreach (Client c in ClientPool)
            {
                NetworkStream networkStream = c.getTcpClient().GetStream();
                if (networkStream.CanRead)
                    handleDownStream(c, networkStream);
                handleUpstream(c, networkStream);
            }
        }
    }

    public void handleDownStream(Client c, NetworkStream networkstream)
    {
        if (networkstream.DataAvailable == false)
            return;

        try
        {
            networkstream.Read(bytesFrom, 0, (int)c.getTcpClient().ReceiveBufferSize);
            dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
            Console.WriteLine("Message From: " + c.getClientIp() + " : " + dataFromClient);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            return;
        }
    }

    public void handleUpstream(Client c, NetworkStream networkstream)
    {
        if (c.getTimeSinceLastMessage() > 30000 && c.getPinged())
        {
            Console.WriteLine("Removing Client From Pool, " + c.getClientIp());
            removeClientFromPool(c);
            return;
        }
        if (c.getTimeSinceLastMessage() > 15000 && c.getPinged() == false)
        {
            Console.WriteLine("Sending ping to Client, " + c.getClientIp());
            c.switchPinged();
            bytesToSend = Encoding.ASCII.GetBytes("ping");
            networkstream.Write(bytesToSend, 0, bytesToSend.Length);
            networkstream.Flush();
            bytesToSend = null;
        }
    }

【讨论】:

  • 其实你做错了。请参阅我对您之前关于此项目的问题的回答。上面的代码解决了您的直接担忧,即没有向您发送任何内容的单个客户端不会阻止您的整个循环,但是您遇到上述方法的其他问题,包括无法有效管理数以万计的客户(正如您在其他问题中指出的那样,这是您的设计目标)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-26
  • 2018-05-11
  • 1970-01-01
  • 1970-01-01
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多