Трюк с сокетом - PullRequest
       13

Трюк с сокетом

0 голосов
/ 04 октября 2010

Я отправляю и получаю байты между сервером и клиентом. Сервер регулярно отправляет некоторые сообщения в виде байтов, а клиент получает их.

Формат сообщения ниже: {Ключ: значение, ключ: Значение, ключ: значение}

Теперь на стороне клиента вместо получения этого сообщения я получаю несколько копий этого сообщения, которое не подходит для этого.

Клиент получает так: {Ключ: значение, ключ: Значение, Key: Value} {Ключ: значение, ключ: Значение, Key: Value} {Ключ: значение, ключ: Значение, Key: Value} {Ключ: значение, ключ: Значение, Key: Value} {Ключ: значение, ключ: Значение, Key: Value} {Ключ: значение, ключ: Значение, Key: Value} {Ключ: значение, ключ: Значение,

Может кто-нибудь помочь мне разобраться в проблеме?

Обновлено


Этот код отправляет инструкции.

var client = (param as System.Net.Sockets.Socket);
            while (true)
            {
                try
                {
                    var instructions = "{";
                    instructions += "Window:" + window + ",";
                    instructions += "Time:" + System.DateTime.Now.ToShortTimeString() + ",";
                    instructions += "Message:" + msgToSend + "";
                    instructions += "}";

                    var bytes = System.Text.Encoding.Default.GetBytes(instructions);
                    client.Send(bytes, 0, bytes.Length, System.Net.Sockets.SocketFlags.None);
                }
                catch (Exception ex)
                {
                    continue;
                }
            }

Этот код получает на стороне клиента.

while (true)
            {
                try
                {
                    var data = new byte[tcpClient.ReceiveBufferSize];
                    stream.Read(data, 0, tcpClient.ReceiveBufferSize);
                    instructions = System.Text.Encoding.Default.GetString(data.ToArray());
                }
                catch (Exception ex)
                {
                    continue;
                }
            }

Ответы [ 4 ]

5 голосов
/ 04 октября 2010

Хорошо, несколько проблем с этим кодом:

  • Вы используете Encoding.Default, что почти определенно не то, что вы хотите сделать
  • Вы всегда декодируете всю строку, а не просто сумму, которую вам действительно удалось прочитать - вы игнорируете возвращаемое значение stream.Read
  • Вы простопродолжение после исключения, без регистрации, обработки ошибок или что-нибудь
  • Как говорит Дин, вы повторно отправляете одни и те же данные

В идеале это будетполезно, чтобы в ваших сообщениях был префикс, указывающий длину каждого в байтах.Затем на принимающей стороне вы можете прочитать эту длину, затем выполнить цикл для многократного чтения в буфер, пока не прочитаете все необходимые данные. Затем выполнить декодирование.

Если вы не можете изменить протокол, вам все равно придется зацикливаться, но явно проверять конечный разделитель ("}") иотмечая, что вы можете получать данные из следующего сообщения, которое вам придется хранить до следующего чтения.

1 голос
/ 04 октября 2010

У вас есть:

while (true)

В отправителе: он будет продолжать посылать одно и то же снова и снова ...

Кроме того, если вы получаете исключение при попытке отправить или получить данные, вы не можете просто повторить попытку и ожидать, что она будет работать. В зависимости от конкретной ошибки, вам может потребоваться восстановить соединение, или может быть, что сеть полностью исчезла. В любом случае, простая повторная попытка почти всегда будет неправильной.

0 голосов
/ 04 октября 2010

Вы отправляете свои данные через TCP.TCP является потоковым протоколом, поэтому вы знаете, что клиент получит тот же поток байтов в том же порядке, но вы потеряете границы пакета.Ваш протокол, кажется, вместо этого ориентирован на пакеты.Тогда у вас есть выбор:

  • переключиться на пакетно-ориентированный протокол (UDP) или
  • разграничить пакеты самостоятельно на принимающей стороне (как сказал Джон Скит, ищаразделители).

Имейте в виду, что TCP имеет некоторые функции надежности, которых нет в UDP.Если надежность не имеет значения, переключитесь на UDP.В противном случае найти разделители на стороне клиента будет проще, чем реализовать собственный уровень надежности.

0 голосов
/ 04 октября 2010

Проблема выяснилась, как сказал Дин Хардинг.
Но кроме того, вы должны быть более понятны в отношении "клиента" или "сервера".
В основном:
Только серверная сторона должна ждать (с помощью цикла) сообщений.Клиент (отправитель) отправляет сообщения в случае необходимости или в состоянии.
Вы можете отправлять сообщения в цикле, но должны контролировать и регулировать их с помощью «Sleep» или «Timer».Таким образом, вы можете сэкономить ресурсы и дать больше времени, чтобы получатель мог полностью обработать сообщение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...