2015-11-11 2 views
1

У меня проблема при работе с сокетами. У меня клиент к серверу должен отправить скриншот. Проблема в том, что сервер не получает все байты из массива, который отправляется клиентом. Постоянно не хватает 255 байт (проверено несколько раз). Соответственно, на стороне сервера я не могу выполнить преобразование из массива байтов обратно в изображение.Socket не получает все байты C# .NET

Клиент отправляет данные на сервер:

byte[] bytesforSend = ConvertBitmapToByteArray(GetScreenImage()); 
client.Send(bytesforSend, bytesforSend.Length, 0); 

recieves сервера данных от клиента:

int lenght = cl.socket.Receive(bytes); 

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

+3

Вы используете TCP-сокеты? Сокеты TCP: * потоковая передача * и не имеют фиксированного начала или конца сообщений, нет * пакетов * в значении, которое имеет UDP. Поэтому вы должны получать в цикле, пока не получите все данные. Кроме того, если вы читаете или записываете изображение, его нужно выполнять в двоичном режиме, а не в текстовом режиме. –

+0

@Joachim Pileborg Я использую TCP-сокет. Попытка получить в цикле. 'Список recievingBytes = новый Список (); Список lenghts = new Список (); int length; do { lenght = cl.socket.Receive (bytes); recievingBytes.Add (байты); lenghts.Add (длина); } while (lenght! = 0); 'Что я делаю неправильно? Первый массив в списке имеет элементы, второй 0 ... – Vitaly

+1

Я не понимаю, как то, что вы говорите, может иметь смысл - поскольку 'bytes' является' Byte [] ', и вы, похоже, не являетесь воссоздавая его, вы добавляете * массив * объект массива в 'receiveBytes' несколько раз, и его содержимое должно быть тем, что осталось там несколькими последовательными вызовами« Получить », переписывая друг друга. –

ответ

0

Позвольте мне вставить здесь код, который вы написали в комментарии:

List<byte[]> recievingBytes = new List<byte[]>(); 
List<int> lenghts = new List<int>(); 
int lenght; do 
{ 
    lenght = cl.socket.Receive(bytes); 
    recievingBytes.Add(bytes); 
    lenghts.Add(lenght); 
} while (lenght != 0); 

Скорее всего, проблема здесь (я видел подобный вопрос в коммерческой библиотеке, сообщенной с камерой) является то, что вы предполагая, что все данные достигнут пункта назначения одновременно, но это не может быть правдой в зависимости от сетевых условий или от того, как клиент фактически отправляет данные.

Предположим, например, что клиент отправляет 2048-байтовый блок данных в четырех 512-байтных сегментах TCP. Первые три поступают незамедлительно, но из-за некоторых проблем с сетью последний пакет теряется и его необходимо повторно передать. В то же время вы уже выполнили проверку while (lenght != 0) и закончили цикл. После, что последний 512 байт приходит, но вы его пропустили.

Что вам нужно сделать, это заменить while(lenght != 0) на что-то вроде while(IDontHaveAllTheDataThatIExpect && !timeout), это предполагает, что вы, конечно, заранее знаете, сколько данных вы получите или сможете каким-то образом определить конец данных.

+1

Предполагая сокет TCP, это неверно. Сокет блокируется, и в этом случае возврат длины «0» происходит только тогда, когда пульт выключил отправку и все данные были получены, или он не блокирует, и в этом случае он выдает исключение, когда он не может получить. (См. [Документация сокета] (https://msdn.microsoft.com/en-us/library/8s4y8aff (v = vs.110) .aspx)).В любом случае проблема будет заключаться в том, что приемник ждет завершения отправки, а не обработки полученных данных, поэтому, если отправитель не отключает соединение, приемник ждет бесконечно. – MicroVirus

+0

@MicroVirus True. Дело в том, что я видел подобную проблему, но это было в неуправляемой библиотеке, где сокеты не работают точно так же, как в .NET. Отсюда мое замешательство. – Konamiman