NetworkStream на порту 21 (FTP) прекращает чтение, когда получает байт со значением 10 (символ новой строки).

У меня есть программа, которая отправляет 88 байт необработанных данных (не строку) с использованием NetworkStream.Read и NetworkStream.Write.

Байт номер 58 имеет значение 10 (новая строка). Поток экземпляра принимающей программы прекращает чтение, как только этот байт получен, действуя как ReadLine вместо Read для необработанных данных.

Сценарий согласуется с тем, что когда я изменил его на чтение 32 байтов за раз, он прочитал 32, а затем 26 (всего 58), останавливаясь на одном и том же байте.

Это когда я запускаю два экземпляра программы на разных машинах, подключенных через Интернет через порт 21. Когда я запускаю оба экземпляра на одной машине, все 88 байтов принимаются без проблем.

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

Изменить: вот код:

Вот код. Он читает данные из одного потока и записывает их в другой, работая в обоих направлениях:

class ProxyConnection
{        
 private NetworkStream clientStream;
 private NetworkStream serverStream;
 public ProxyConnection()
 {
..            clientStream = tcpClient.GetStream();
            serverStream = tcpServer.GetStream();
..}

 private void RouteFromClientToServer()
 {
   Message message;
   while (true)
   {
     try
     {
       message = ReadMessageFromClient();
       ValidateMessage(message);
       SendMessageToServer(message);
     }
     catch(IOException e)
     {
      Logger.getInstance().log(e.Message);
      break;
     }
    }
}
        private Message ReadMessageFromClient()
        {
            Message message = new Message();
            message.bytes = new byte[MESSAGE_SIZE];
            message.bytesCount = clientStream.Read(message.bytes, 0, MESSAGE_SIZE);
            Logger.getInstance().log("Size ( " + message.bytesCount + " ) From Client");
            return message;
 }



    private void SendMessageToServer(Message message)
    {      
        serverStream.Write(message.bytes, 0, message.bytesCount);
        Logger.getInstance().log("Size ( " + message.bytesCount + " ) To Server");
        serverStream.Flush();
    }


}

person Ahmed Nasser    schedule 28.12.2011    source источник
comment
Можете ли вы опубликовать код, который вы используете для чтения данных? Используете ли вы какой-то прокси между машинами?   -  person Jeremy McGee    schedule 28.12.2011
comment
Сможет ли он прочитать остальное, если вы прочитаете еще раз?   -  person cHao    schedule 28.12.2011
comment
@JeremyMcGee Я добавил код. Одна из машин находится у меня на рабочем месте, поэтому может быть прокси.   -  person Ahmed Nasser    schedule 28.12.2011
comment
@cHao Нет, это блокирует .. Когда я читаю 32 за раз, он читает 32, затем 26, а затем блокирует   -  person Ahmed Nasser    schedule 28.12.2011
comment
@Ahmed: этого кода недостаточно для воспроизведения проблемы. Код, как мы его видим, не должен иметь никаких проблем, если только какой-то код, которого мы здесь не видим, не мешает потокам. Мне только что удалось реализовать половину прокси с ним.   -  person cHao    schedule 28.12.2011
comment
@chao Очевидно, проблема заключалась в том, что клиент находился за прокси-сервером, который самостоятельно манипулировал данными. Я использовал порт 21 (первоначально FTP-порт), поэтому, вероятно, прокси-сервер на рабочем месте обрабатывал этот порт особым образом. Когда я перешел на порт 1863, все заработало как шарм :). Большое спасибо за ваше время, это действительно ценно.   -  person Ahmed Nasser    schedule 29.12.2011
comment
@jeremymcgee Спасибо за ваше время. Это была проблема с прокси. Спасибо за помощь.   -  person Ahmed Nasser    schedule 29.12.2011
comment
О да. Это стоит ответа, я отредактирую ваш вопрос, чтобы другие люди, приходящие из Google, в будущем имели половину шансов найти это. Это может привести к часам отладки!   -  person Jeremy McGee    schedule 29.12.2011


Ответы (2)


Сокеты TCP не особенно заботятся о том, сколько байтов вы хотите отправить или получить за раз. Если данные или пространство доступны, он будет получать или отправлять столько, сколько вы можете обработать. Если нет места или данных, отправка или получение могут быть заблокированы до тех пор, пока они не смогут что-то сделать. Но если в буфере есть место для 10 байт, а вы отправляете 50, то сокет с радостью поместит 10 байт в буфер и скажет: «Отправлено 10 байт. Попробуйте отправить остальные через бит». Точно так же, если доступно 10 байт, а вы хотите 50, сокет говорит: «Вот 10. Делайте, пока у меня не будет больше». Последующий прием или отправка в сокете обычно блокируются до тех пор, пока не будет больше данных или места, а затем считываются или записываются столько, сколько доступно в это время. Вот почему они возвращают, сколько данных им удалось перетасовать.

Вполне возможно, что происходит какое-то волшебство (например, автоматическое сбрасывание при отправке 10), чтобы упростить обработку текста в потоке, поскольку это такой распространенный вариант использования. Но если вы прочитаете еще раз, вы должны получить больше данных. Если чтение не возвращает 0 байтов - это обычно означает, что соединение было закрыто, и что вы не закрываете сокет, прежде чем закрыть/утилизировать его.

person cHao    schedule 28.12.2011
comment
Вот класс. Он читает данные из одного потока и записывает их в другой, работая в обоих направлениях: - person Ahmed Nasser; 28.12.2011
comment
Ваш опубликованный код не работал, но как только я добавил код для настройки потоков и добавил функцию-заглушку ValidateMessage и классы Message и Logger, он работает нормально. У него нет проблем, которые могли бы помешать ему доставить все, хотя нет гарантии, что он будет передаваться частями любого заданного размера. Проблема в другом... будь то код, который вы не опубликовали, или клиент или сервер. - person cHao; 29.12.2011

Какой порт вы используете? Есть ли прокси-сервер?

В частности, если вы используете порт 21 (FTP), некоторые прокси-серверы имеют особую обработку пассивного FTP. Я считаю, что для этого требуется, чтобы прокси-сервер сканировал трафик, поэтому, в частности, если команды недействительны, вы увидите, что прокси-сервер закрывает соединение сокета.

Обходной путь... используйте другой порт.

person Jeremy McGee    schedule 29.12.2011