C # отправка файлов через интернет - PullRequest
0 голосов
/ 25 ноября 2011

Мне удалось отправить двоичные данные через TCP, используя NetworkStream и сокеты.Моя единственная проблема заключается в том, что когда я отправляю файлы большего размера, например, несколько сотен изображений КБ, они не передаются правильно, половина изображения отсутствует.На стороне сервера я Socket.Send для передачи данных.На стороне клиента я использую Socket.BeginReceive с буфером размером 1024, который записывается в MemoryStream, позже я использую new Bitmap(Stream) для преобразования этого MemoryStream в изображение, которое может быть отображено в PictureBox.

Какой метод следует использовать, чтобы избежать потери данных?

Редактировать: отправленный код

            listener = new TcpListener(myAddress, 86);
            listener.Start();
            TcpClient client = listener.AcceptTcpClient();
            ns = client.GetStream();
            byte[] buffer = new byte[1024];
            while (fileTransfer)
            {
                ms = new MemoryStream();
                do
                {
                    int length = ns.Read(buffer, 0, buffer.Length);
                    ms.Write(buffer, 0, length);
                    // with this line added the data loss apparently disappears
                    System.Threading.Thread.Sleep(1);
                } while (ns.DataAvailable);
                UpdateData();
                ms.Dispose();
                System.Threading.Thread.Sleep(10);
            }
            ns.Dispose();
            client.Close();
            listener.Stop();

Редактировать: данные все еще иногда повреждены даже при использовании метода сна.

Ответы [ 3 ]

1 голос
/ 26 ноября 2011

Я предлагаю вам изменить этот цикл:

do
{
    int length = ns.Read(buffer, 0, buffer.Length);
    ms.Write(buffer, 0, length);
    // with this line added the data loss apparently disappears
    System.Threading.Thread.Sleep(1);
} while (ns.DataAvailable);

в

do
{
    int length = ns.Read(buffer, 0, buffer.Length);
    ms.Write(buffer, 0, length);
} while (length > 0);

То есть читать до конца данных (т.е. ns.Read не возвращает данных). Read блокируется, пока не появятся какие-либо данные или сокет не будет закрыт (или не будет сгенерировано исключение). Я снял бесполезный сон.

0 голосов
/ 26 ноября 2011

ОК. Я решил это, отправив размер данных перед отправкой фактических данных. Причина, по которой это не сработало, заключается в том, что я ошибочно предположил, что перевод был немедленным. Вот почему метод Sleep () в цикле приемника изменил ситуацию, но НЕ решил ее. Я понимаю, что я не могу полагаться на DataAvailable в этом контексте. Даже проверка длины полученных данных не сработает, потому что клиент может отправить данные после завершения цикла. Проверка размера файла (если данные больше, чем буфер на стороне получателя) - лучшее решение, которое я нашел так долго.

0 голосов
/ 25 ноября 2011

Скорее всего (по предположению) вы не правильно читаете из потока на стороне клиента.

Вам нужно прочитать результат метода EndReceive (), чтобы увидеть, сколько данных вы на самом деле читаете -это может быть не размер вашего буфера (в данном случае 1024 байта)

Итак:
a) При вызове BeginReceive вы передаете обратный вызов?
b) Если да, вы читаетерезультат этого и запись соответствующего количества байтов в ваш поток памяти?

т.е.:

public void ReceiveCallback( IAsyncResult result)
{

    var buffer = (byte[])result.AsyncState;
    int bytesRead = socket.EndReceive();
    memoryStream.Write (buffer, 0, bytesRead);//bytesRead may not be 1024!
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...