Передача изображения с помощью TCP-сокетов в Linux - PullRequest
1 голос
/ 21 июля 2009

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

Ответы [ 3 ]

3 голосов
/ 21 июля 2009

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

Это означает, что при чтении вы можете получить меньше байтов, чем запрашиваете. Например, если ваше изображение 128 КБ, вы можете получить только 24 КБ при первом чтении, что потребует повторного чтения, чтобы получить остальные данные. Тот факт, что это изображение не имеет значения. Данные есть данные.

Например:

int read_image(int sock, int size, unsigned char *buf) {
   int bytes_read = 0, len = 0;
   while (bytes_read < size && ((len = recv(sock, buf + bytes_read,size-bytes_read, 0)) > 0)) {
       bytes_read += len;
   }
   if (len == 0 || len < 0) doerror();
   return bytes_read;
}
1 голос
/ 21 июля 2009

TCP отправляет данные по частям, поэтому вы не гарантированно получите их все сразу за одно чтение (хотя гарантированно останетесь в том порядке, в котором вы их отправили). Вы в основном должны читать несколько раз, пока не получите все данные. Он также не знает, сколько данных вы отправили на стороне получателя. Обычно вы отправляете поле фиксированной длины «длина» вначале (например, всегда 8 байт), чтобы вы знали, сколько там данных. Затем вы продолжаете читать и строить буфер, пока не получите столько байтов.

Таким образом, отправитель будет выглядеть примерно так (псевдокод)

int imageLength;
char *imageData;

// set imageLength and imageData

send(&imageLength, sizeof(int));
send(imageData, imageLength);

И получатель будет выглядеть так (псевдокод)

int imageLength;
char *imageData;

guaranteed_read(&imageLength, sizeof(int));
imageData = new char[imageLength];
guaranteed_read(imageData, imageLength);

void guaranteed_read(char* destBuf, int length)
{
    int totalRead=0, numRead;
    while(totalRead < length)
    {
        int remaining = length - totalRead;
        numRead = read(&destBuf[totalRead], remaining);
        if(numRead > 0)
        {
            totalRead += numRead;
        }
        else
        {
            // error reading from socket
        }
    }
}

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

0 голосов
/ 21 июля 2009

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

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