Переключить строки операторов, соответствующие, но не работающие - PullRequest
0 голосов
/ 28 января 2019

У меня есть оператор 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;
        }
    }

Я не могу получить егокод по умолчанию.

Кроме того, поскольку я новичок в программировании клиент / сервер и сокет, я только что понял, что сервер отправляет байт [], но клиент получает символ [].Есть ли там конфликт?Есть ли какая-то конкретная причина для этого (поскольку я использую эти конкретные фрагменты кода из онлайн-тренинга)?

1 Ответ

0 голосов
/ 28 января 2019

Первая проблема, которую я вижу, заключается в том, что вы игнорируете 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);
}
...