【问题标题】:Switch statement strings matching but not functioningSwitch 语句字符串匹配但不起作用
【发布时间】:2019-01-28 12:44:57
【问题描述】:

我有一个 switch 语句,它使用从 char[] 转换而来的字符串,该字符串通过数据流从服务器发送到客户端。代码是客户端的。

即使服务器和默认错误代码始终完全匹配大小写,也会始终命中默认大小写。

SERVER SIDE
private void SendToClient(string message, TcpAccount account)
    {
        try
        {
            byte[] buffMessage = Encoding.ASCII.GetBytes(message);
            account.TcpClient.GetStream().WriteAsync(buffMessage, 0, buffMessage.Length);
            log.AppendText(string.Format("Message {0} sent to account {1}", message, account.ID));
            log.AppendText(Environment.NewLine);
        }
        catch
        {
            log.AppendText(string.Format("Message {0} sent to account {1}", message, account.ID));
            log.AppendText(Environment.NewLine);
        }
    }

CLIENT SIDE
public async void ReadDataAsync(TcpClient client)
    {
        try
        {
            StreamReader clientStreamReader = new StreamReader(client.GetStream());
            char[] buff = new char[64];
            int readByteCount = 0;

            while (true)
            {
                readByteCount = await clientStreamReader.ReadAsync(buff, 0, buff.Length);

                if (readByteCount <= 0)
                {
                    Console.WriteLine("Disconnected from server.");
                    client.Close();
                    break;
                }
                string code = new string(buff);
                ProcessServerCode(code);
                Array.Clear(buff, 0, buff.Length);
            }
        }
        catch
        {

        }
    }

public void ProcessServerCode(string code)
    {
        switch (code)
        {
            case "regcom":
                MessageBox.Show("Registration Complete");
                break;

            case "logcom":
                MessageBox.Show("Login Complete");
                break;

            case "badpass":
                MessageBox.Show("Invalid Password");
                break;

            case "badaccount":
                MessageBox.Show("Invalid Account");
                break;

            default:
                MessageBox.Show("Unknown Code: " + code);
                break;
        }
    }

我无法从默认代码中删除它。

另外,由于我是客户端/服务器和套接字编程的新手,我刚刚意识到服务器发送一个字节[],但客户端接收一个字符[]。那里有冲突吗?有什么特别的原因(因为我使用的是在线培训课程中的那些特定代码)?

【问题讨论】:

  • 您是否尝试调试客户端代码接收到的内容?如果你总是点击默认值,那么你的输入不是你所期望的
  • 您可以尝试修剪收到的字符串,更新此行string code = new string(buff).Trim();。我认为这可能是一个原因,因为您等待接收 64 个字节,但在您的示例中接收到的字符串较少
  • 旁注:从不使用async void。即使您不关心结果,您也应该始终使用async Task。这里的一个关键原因是 async 关心同步上下文,并且存在许多 主动阻止 async void 的同步上下文 - 特别是但不限于 ASP.NET 同步上下文.这意味着您可以发现代码在一个系统中运行良好,而当您更改版本/平台/等时,由于同步上下文差异(一个允许 async void,一个不允许)。所以:永远不要使用async void
  • @MarcGravell 谢谢!我已经进行了更改,并且一定会在将来避免异步无效。
  • 另一个旁注:你实际上不是await-ing WriteAsync - 你真的应该等待

标签: c# arrays string tcp switch-statement


【解决方案1】:

我看到的第一个问题是您忽略了readByteCount(实际上是字符数,而不是字节数);你应该使用:

string code = new string(buff, 0, readByteCount);

但是,我看到的下一个问题是您没有任何帧协议。这意味着:

  • 如果两条消息紧密相连,您可能会收到看似单个串联值的内容
  • 即使是单个值在数据包之间拆分时也可能被任意截断

无论哪种情况:

  • 如果消息长于缓冲区长度,你就坏了
  • 如果您一次收到多条消息,那您就完蛋了

无论哪种情况,都无法正确恢复位置。因此:帧,其中每一帧都是完整的消息。

基于文本的协议的一种常见方法是使用换行符作为框架(我会让你决定这是否意味着 CR、LF、CRLF 等);那么您可以在文本阅读器上使用ReadLine / ReadLineAsync,它会自动完成所有操作,所以:

string code = await clientStreamReader.ReadLineAsync();
if (code is null)
{
    Console.WriteLine("Disconnected from server.");
    client.Close();
}
else
{
    ProcessServerCode(code);
}

【讨论】:

  • ("它会自动完成" > 只要你别忘了在有效载荷中转义行尾...)
  • @PatrickHofman 确实:) 实际上,如果我是迂腐的,我会说“避免在套接字服务器中使用TextReader - 手动处理帧,只有在你有整个帧时才解码, 理想情况下使用像“管道”这样的东西作为引擎”,但这需要 很多 比我在星期一可以管理的更多解释......
  • @MarcGravell 因此,专注于第一个问题,将代码更改为您的第一行给了我相同的结果。默认显示我收到“regcom”作为代码,但它在技术上与“regcom”大小写不匹配。在眼睛看来它们匹配,但不知何故在代码中它们不匹配。至于你的其他笔记,这一切似乎都超出了我的范围(我对任何类型的网络通信都很陌生),但是使用方法 ReadLineAsync(),客户端不再成功接收来自服务器的任何消息。我需要在服务器端进行其他更改吗?
  • @Arcaster 是的,帧需要在两端匹配;最简单的解决方法是byte[] buffMessage = Encoding.ASCII.GetBytes(message + "\r\n");(但也可以采用更有效的方法)
  • @Arcaster 关于“将代码更改为您的第一行”问题;不幸的是,为了进一步诊断,我真的需要逐字节查看,而且由于框架问题,这种方法注定会失败无论如何 - 所以我不确定它是否值得我们的时间试图更进一步
猜你喜欢
  • 2018-10-02
  • 2011-02-23
  • 2023-02-20
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-23
  • 1970-01-01
相关资源
最近更新 更多