реклама на сайте
подробности

 
 
> Сервер На Wiznet W5500, передать изображение
mr_smit
сообщение May 12 2015, 04:30
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



Прикупил у китайцев плату с чипом W5500. Это обновленная версия Ethernet чипа W5100. Подключил к STM32 Discovery. За основу взял эту статью: http://we.easyelectronics.ru/GYUR22/w5500s...web-server.html. Убрал функции работы с SD картой и скомпилировал всё это в CooCox. Сервер заработал. Т.е. отдает в браузер статичный текст.

Хочу добавить на html страницу картинку. Для теста сделал PNG размером 5х5 пикселей. Добавил её в html код:
CODE

<html>
<head>
<title>Умный дом</title>
<meta http-equiv='content-type' content='text/html; charset=windows-1251'>
</head>
<body>
<br><br><br><center><b>Тестовая страница W5500</b></center><br>
<center><img src='test.png'></center>
</body>
</html>


Открыл картинку в hex редакторе и сделал массив сырых данных:
CODE
const char Img [205] =
{
0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52,
0x00,0x00,0x00,0x05,
0x00,0x00,0x00,0x05,0x08,0x02,0x00,0x00,0x00,0x02,0x0D,0xB1,0xB2,0x00,0x00,0x00,
0x01,0x73,0x52,0x47,
0x42,0x00,0xAE,0xCE,0x1C,0xE9,0x00,0x00,0x00,0x06,0x62,0x4B,0x47,0x44,0x00,0xFF,
0x00,0xFF,0x00,0xFF,
0xA0,0xBD,0xA7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0B,0x13,
0x00,0x00,0x0B,0x13,
0x01,0x00,0x9A,0x9C,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4D,0x45,0x07,0xDF,0x05,
0x0A,0x0E,0x01,0x20,
0xA0,0x0A,0x57,0xCD,0x00,0x00,0x00,0x19,0x74,0x45,0x58,0x74,0x43,0x6F,0x6D,0x6D,
0x65,0x6E,0x74,0x00,
0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4D,
0x50,0x57,0x81,0x0E,
0x17,0x00,0x00,0x00,0x28,0x49,0x44,0x41,0x54,0x08,0xD7,0x4D,0x8B,0x41,0x0E,0x00,
0x30,0x08,0xC2,0xA8,
0xFF,0xFF,0x73,0x3D,0x18,0xDD,0xB8,0x34,0x94,0x40,0x12,0x35,0x9B,0x52,0x81,0xD7,
0x67,0x3F,0x55,0x83,
0x53,0xFC,0x67,0xA0,0x01,0x8E,0xCE,0x0F,0x06,0x6E,0x28,0x44,0x78,0x00,0x00,0x00,
0x00,0x49,0x45,0x4E,
0x44,0xAE,0x42,0x60,0x82
};


А в функции tcp_http_mt добавил реакцию на запрос картинки. Т.е. при ответе к HTTP заголовку приклеиваем сырые данные картинки.

CODE
int32_t tcp_http_mt(uint8_t sn, uint8_t* buf, uint16_t port)
{
int32_t ret;
uint32_t size = 0;
char *url,*p;

switch(getSn_SR(sn))
{
case SOCK_ESTABLISHED :

if(getSn_IR(sn) & Sn_IR_CON)
{
setSn_IR(sn,Sn_IR_CON);
}

if((size = getSn_RX_RSR(sn)) > 0)
{
if(size > DATA_BUF_SIZE)
{
size = DATA_BUF_SIZE;
}

ret = recv(sn,buf,size);

HTTP_reset(sn);

if(ret <= 0)
{
return ret;
}

url =(char*) buf + 4;

if((http_state[sn]==HTTP_IDLE)&&(memcmp(buf, "GET ", 4)==0)&&((p = strchr(url, ' ')))) // extract URL from request header
{
*(p++) = 0; //making zeroed url string

sentsize[sn]=0;

if(strcmp(url,"/")==0)
{
strcpy((char*)buf,http_200);
strcat((char*)buf, http_server);
strcat((char*)buf,"Content-Type: text/html; charset=windows-1251\r\n");
strcat((char*)buf,"Cache-Control: no-cache\r\n");
strcat((char*)buf,http_connection_close);
strcat((char*)buf, http_header_end);
strcat((char*)buf,site);
size=strlen((char*)buf);
http_state[sn]=HTTP_SENDING;
}

if(strcmp(url,"/test.png")==0)
{
strcpy((char*)buf,http_200);
strcat((char*)buf, http_server);
strcat((char*)buf,"Content-Type: image/png\r\n");
//
strcat((char*)buf,"Content-Lenght: 205\r\n");
strcat((char*)buf,"Connection: keep-alive\r\n");
strcat((char*)buf,"Keep-Alive: timeout=20\r\n");
strcat((char*)buf,"Accept-Ranges: bytes\r\n");
strcat((char*)buf,"Cache-Control: no-cache\r\n");
strcat((char*)buf, http_header_end);
strcat((char*)buf,Img);
size=strlen((char*)buf);
http_state[sn]=HTTP_SENDING;
}
}

/*
Отправляем данные пока размер отправленных данных sentsize[sn] не сравняется с размером данных size
которые мы подготовили для отправки

... вроде бы...
*/
if(http_state[sn]==HTTP_SENDING)
{
while (sentsize[sn] < size)
{
//DATA_BUF_SIZE

ret = send(sn,buf,size);
if(ret < 0)
{
close(sn);
return ret;
}
sentsize[sn] += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
HTTP_reset(sn);
disconnect(sn);
}
}

break;

case SOCK_CLOSE_WAIT :

HTTP_reset(sn);

if((ret=disconnect(sn)) != SOCK_OK)
return ret;

break;
case SOCK_INIT :

HTTP_reset(sn);

if( (ret = listen(sn)) != SOCK_OK) return ret;
break;
case SOCK_CLOSED:

HTTP_reset(sn);

if((ret=socket(sn,Sn_MR_TCP,port,0x00)) != sn)
return ret;

break;

default:
HTTP_reset(sn);
break;
}
return 1;
}


В итоге запрос на картинку в браузере идет, но сервер её не отдает.
Прикрепленное изображение

При этом браузер получает заголовки ответа. Но самого изображения нет.

От безысходности установил HTTP снифер Wireshark. Удалось выяснить, что при передаче картинки сервер отправляет только её первые 8 байт. И на этом всё.
Прикрепленное изображение


3-й день бьюсь. Не понимаю почему так происходит. Или где то функцию отправки надо изменить или с размером передаваемых данных что то не то. Гуглил и по W5100 и по W5200 и по W5500, но именно как передать изображение не нашел.

Прикрепленный файл  web_discovery_w5500_sd.zip ( 557.27 килобайт ) Кол-во скачиваний: 45


Может есть у кого какие идеи?
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 17)
AlanDrakes
сообщение May 12 2015, 05:12
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 101
Регистрация: 2-05-15
Из: Россия, Омск
Пользователь №: 86 474



Вы пытаетесь поместить бинарный файл в строку.
Код
img[] {0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,0x0D ... };

Код
                              strcat((char*)buf, http_header_end);
                              strcat((char*)buf,Img);
                              size=strlen((char*)buf);

Но на символе конца строки функция и останавливается.
Но функция копирования строки останавливается на символе 0x00 - нуль-терминатор.
Вам нужен бинарный буфер вместо строкового.
И попробуйте сделать через memcpy:
Код
strcat((char*)buf, http_header_end); // Заголовок... и всё, что до него.
size=strlen((char*)buf); // Текущий размер строк в буфере
memcpy((char*)buf,Img[0]*, sizeof(Img)); // Копируем картинку в буфер.
size += sizeof(Img); // Увеличиваем на размер картинки.

Где-то мог случайно ошибиться.
Но на вид всё должно заработать.

Исправления касаются только main.c

Сообщение отредактировал AlanDrakes - May 12 2015, 05:14
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 12 2015, 05:51
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



Цитата(AlanDrakes @ May 12 2015, 09:12) *
Но функция копирования строки останавливается на символе 0x00 - нуль-терминатор.
Вам нужен бинарный буфер вместо строкового.
И попробуйте сделать через memcpy:

Точно. Похоже на правду. Спасибо! Проверить, к сожалению, смогу только вечером.

Сообщение отредактировал mr_smit - May 12 2015, 06:01
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 12 2015, 07:56
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



Код
strcat((char*)buf, http_header_end); // Заголовок... и всё, что до него.
size=strlen((char*)buf); // Текущий размер строк в буфере
memcpy((char*)buf,Img[0]*, sizeof(Img)); // Копируем картинку в буфер.
size += sizeof(Img); // Увеличиваем на размер картинки.


А в таком случае разве memcpy не затрет buf? И в buf будет только сама картинка без заголовков?

Может отправить сначала заголовок, а затем картинку?
Код
ret = send(sn,buf, strlen(buf));
ret = send(sn, Img, sizeof(Img));


Сообщение отредактировал mr_smit - May 12 2015, 07:56
Go to the top of the page
 
+Quote Post
kolobok0
сообщение May 12 2015, 08:35
Сообщение #5


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(mr_smit @ May 12 2015, 10:56) *
....А в таком случае разве memcpy не затрет buf? И в buf будет только сама картинка без заголовков?...


конечно же затрёт. И ещё пять копеек. Картинку Вы точно в бинарном виде собрались передавать, а не в base64?
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 12 2015, 09:08
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



Цитата(kolobok0 @ May 12 2015, 12:35) *
конечно же затрёт. И ещё пять копеек. Картинку Вы точно в бинарном виде собрались передавать, а не в base64?

В бинарном. Я посмотрел, браузер получает картинки в чистом виде. Для этого указывается тип (image/png, image/jpg и т.д.) и количество байт.

Хотя черт его знает:
Прикрепленное изображение


Надо попробовать в base64 конвертнуть и strcat-ом приклеить.

Сообщение отредактировал mr_smit - May 12 2015, 09:28
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 12 2015, 16:27
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



В общем работают оба способа. Если при запросе картинки отдать сначала заголовок, а потом сырые данные картинки, то она отображается.
Код
ret = send(sn,buf,size);
ret = send(sn,(char*)Img, sizeof(Img));


Так же можно вставить картинку в кодировке base64 непосредственно в html код страницы.
Код
const char site[] =
        "<html>"
        "<head>"
        "<title>Умный дом</title>"
        "<meta http-equiv='content-type' content='text/html; charset=windows-1251'>"
        "</head>"
    "<body>"
        "<br><br><br><center><b>Тестовая страница W5500</b></center><br>"
        "<center><img src='data:image/png;base64,"

        "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A"
        "/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB98FCg4BIKAKV80AAAAZdEVYdENv"
        "bW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAKElEQVQI102LQQ4AMAjCqP//cz0Y3bg0lEAS"
        "NZtSgddnP1WDU/xnoAGOzg8GbihEeAAAAABJRU5ErkJggg=="
                "'></center>"
    "</body>"
    "</html>";


В этом случае при запросе страницы она открывается корректно с картинкой. Но когда я взял картинку размером 5 КБ, то страница не открывается. Постоянно висит ожидание.

Размер передающего буфера 2 КБ. Т.е. надо разбить данные на блоки. Вот это место:
Код
...
sentsize[sn]=0;
...

if(http_state[sn]==HTTP_SENDING)
               {
                 while (sentsize[sn] < size)
                 {
                 ret = send(sn,buf+sentsize[sn],size-sentsize[sn]);

                      if(ret < 0)
                      {
                      close(sn);
                      return ret;
                      }

                 sentsize[sn] += ret;   // Don't care SOCKERR_BUSY, because it is zero.
                 }
                 HTTP_reset(sn);
                 disconnect(sn);
              }


ret длина реально отправленных данных. Опять же не уловлю в чем проблема.
Go to the top of the page
 
+Quote Post
AlanDrakes
сообщение May 13 2015, 04:06
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 101
Регистрация: 2-05-15
Из: Россия, Омск
Пользователь №: 86 474



Цитата(mr_smit @ May 12 2015, 13:56) *
Код
strcat((char*)buf, http_header_end); // Заголовок... и всё, что до него.
size=strlen((char*)buf); // Текущий размер строк в буфере
memcpy((char*)buf,Img[0]*, sizeof(Img)); // Копируем картинку в буфер.
size += sizeof(Img); // Увеличиваем на размер картинки.


А в таком случае разве memcpy не затрет buf? И в buf будет только сама картинка без заголовков?

Может отправить сначала заголовок, а затем картинку?
Код
ret = send(sn,buf, strlen(buf));
ret = send(sn, Img, sizeof(Img));


А, да, видимо, как раз там и ошибся.
Тогда, передавая картинку бинарными данными, нужно делать так:
Код
strcat((char*)buf, http_header_end); // Заголовок... и всё, что до него.
size=strlen((char*)buf); // Текущий размер строк в буфере
memcpy((char*)buf+size,Img[0]*, sizeof(Img)); // Копируем картинку в буфер (со смещением на _размер_ заголовков).
size += sizeof(Img); // Увеличиваем на размер картинки.

Но здесь есть вероятность получить переполнение буфера... со всеми вытекающими. Так что, нужно делать очень осторожно.

А вообще, для передачи бинарных данных, нужно использовать строку-разделитель. Она же передаётся в заголовке.
Но тогда у Вас будет очень большой буфер отправки и он может не поместиться в RAM контроллера.
Опять же, грабли.

По отправке:
Код
if(http_state[sn]==HTTP_SENDING)
               {
                 while (sentsize[sn] < size)
                 {
                 ret = send(sn,buf+sentsize[sn],size-sentsize[sn]);

send() принимает ссылку на буфер? С библиотекой я не знаком, но кажется, Вы получаете на второй итерации выход за границы массива.
Попробуйте так:
Код
ret = send(sn,buf,size-sentsize[sn]);

Опять же, возможно, ошибаюсь..
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 13 2015, 09:17
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



Код
int32_t send(uint8_t sn, uint8_t * buf, uint16_t len)


Я пока никак не пойму можно ли большой массив передать порциями по 2 КБ. В смысле поддерживает само железо такой финт или нет. Но судя по всему поддерживает, ведь человек из вышеприведенной статьи как то загружает сайт с SD карточки.

Сообщение отредактировал mr_smit - May 13 2015, 09:50
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 13 2015, 13:23
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



Сделал так:
Код
ret = send(sn,buf,size);  // отправляем заголовок

ret = send(sn,(char*)Img1,sizeof(Img1)); // картинка по частям
ret = send(sn,(char*)Img2,sizeof(Img2)); //
ret = send(sn,(char*)Img3,sizeof(Img3)); //

disconnect(sn);

в итоге загружается только первая треть картинки или даже меньше:
Прикрепленное изображение

Сообщение отредактировал mr_smit - May 13 2015, 13:26
Go to the top of the page
 
+Quote Post
AlanDrakes
сообщение May 13 2015, 14:46
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 101
Регистрация: 2-05-15
Из: Россия, Омск
Пользователь №: 86 474



Передавать нужно, убедившись, что сокет готов отправлять следующую порцию данных.
Я бы не рекомендовал передавать за раз более 1400 байт (MTU пакета как правило, ~1500, но лучше ограничить чуть меньшим объёмом) и, если библиотека только записывает данные в ETH, но не проверяет их отправку - то проверять это самостоятельно.
Если мне не слишком изменяет память, то W5500 должен быть близок к W5100 в плане памяти - 8кB на 4 сокета, то есть, 2кБ/сокет (приём и передача отдельные), куда записываются сформированные пакеты.

А человек, предположительно, загружает меньшими порциями.
Кстати, его код пробовали разобрать для понимания? То есть, его последовательность действий:
Чтение файла, обработка, передача... и т.п.?
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 13 2015, 17:56
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



Цитата(AlanDrakes @ May 13 2015, 18:46) *
Кстати, его код пробовали разобрать для понимания? То есть, его последовательность действий:
Чтение файла, обработка, передача... и т.п.?

Так я его исходник и правлю. Функция Send, как я понимаю, сама следит за передающим буфером:
CODE
int32_t send(uint8_t sn, uint8_t * buf, uint16_t len)
{
uint8_t tmp=0;
uint16_t freesize=0;

CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKDATA();
tmp = getSn_SR(sn);
if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
if( sock_is_sending & (1<<sn) )
{
tmp = getSn_IR(sn);
if(tmp & Sn_IR_SENDOK)
{
setSn_IR(sn, Sn_IR_SENDOK);
#if _WZICHIP_ == 5200
if(getSn_TX_RD(sn) != sock_next_rd[sn])
{
setSn_CR(sn,Sn_CR_SEND);
while(getSn_CR(sn));
return SOCKERR_BUSY;
}
#endif
sock_is_sending &= ~(1<<sn);
}
else if(tmp & Sn_IR_TIMEOUT)
{
close(sn);
return SOCKERR_TIMEOUT;
}
else return SOCK_BUSY;
}
freesize = getSn_TxMAX(sn);
if (len > freesize) len = freesize; // check size not to exceed MAX size.
while(1)
{
freesize = getSn_TX_FSR(sn);
tmp = getSn_SR(sn);
if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
{
close(sn);
return SOCKERR_SOCKSTATUS;
}
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
if(len <= freesize) break;
}
wiz_send_data(sn, buf, len);
#if _WIZCHIP_ == 5200
sock_next_rd[sn] = getSn_TX_RD(sn) + len;
#endif
setSn_CR(sn,Sn_CR_SEND);
/* wait to process the command... */
while(getSn_CR(sn));
sock_is_sending |= (1 << sn);
return len;
}


А отправляет он так:
Код
if(fs[sn].fsize != sentsize[sn])
                {

                  f_read(&fs[sn], &buf[header_sz], DATA_BUF_SIZE-header_sz, &blocklen);

                   ret = send(sn,buf,blocklen+header_sz);

                   if(ret < 0)
                   {
                    f_close(&fs[sn]);
                    close(sn);
                    return ret;
                   }

                  sentsize[sn] += ret; // Don't care SOCKERR_BUSY, because it is zero.
                 }

Читает с карты 2048 байт минус размер HTTP заголовка (DATA_BUF_SIZE-header_sz). А отправляет по факту каждый раз 2048 байт (blocklen+header_sz) кроме последней итерации.

Сейчас только заметил blocklen+header_sz. Может надо HTTP заголовок отправлять с каждым куском данных??? Я то сейчас отправляю заголовок, а потом просто куски картинки. А у него в буфере каждый раз оказывается заголовок + новая порция считанных данных &buf[header_sz]. Правильно?

Сообщение отредактировал IgorKossak - May 14 2015, 12:28
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
Go to the top of the page
 
+Quote Post
kolobok0
сообщение May 13 2015, 19:01
Сообщение #13


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(mr_smit @ May 13 2015, 20:56) *
Код
...                 f_read(&fs[sn], &buf[header_sz], DATA_BUF_SIZE-header_sz, &blocklen);

                   ret = send(sn,buf,blocklen+header_sz);
...

Читает с карты 2048 байт минус размер HTTP заголовка...


ышо 5 копеек.
Вы попали в типичную ошибку для протокола TCP. Это протокол ПОТОКОВЫЙ(!) т.е. при вычитывании из буффера может прийти ЛЮБОЕ
кол-во байт в пределах максимально переданного кол-ва. Т.е.

Передатчик передаёт
500+500+24
Приёмник МОЖЕТ принять
24+100+100+300+400+50+50

почувствуйте разницу...
PS
Особенно эти ослинные уши начинают лезть, когда система начинает работать в боевых сетях - с различным временным лагом
прихода пакетов на IP уровне, с доп. разборкой-сборкой на IP уровне, и т.д..

Сообщение отредактировал kolobok0 - May 13 2015, 19:03
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 14 2015, 03:26
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



Цитата(kolobok0 @ May 13 2015, 23:01) *
Передатчик передаёт
500+500+24
Приёмник МОЖЕТ принять
24+100+100+300+400+50+50

почувствуйте разницу...

Выходит надо учитывать переменную ret. Это число реально переданных байт. И в зависимости от неё двигать указатель в буфере отправки buf при посылке следующей части. Но вопрос о прикреплении заголовка к каждой части посылки остается открытым.
Go to the top of the page
 
+Quote Post
AlanDrakes
сообщение May 14 2015, 09:59
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 101
Регистрация: 2-05-15
Из: Россия, Омск
Пользователь №: 86 474



Нет, по идее, не нужно к каждой посылке прикреплять заголовок, т.к. в этом случае будет нарушен поток. А вот TCP заголовок - да. Но, думаю, это делает сама функция, так что не фатально.
Процедура, похоже, действительно обрабатывает количество байт, но там идёт что-то, связанное с допустимыми значениями... я в задумчивости..
Эх, формировал сам пакеты - не было проблем... они уходили такими, какими должны. А вот W5100 и выше умеют сокеты и там уже хитрее - писать нужно в сокет, а чип позаботится об отправке пакета(-ов).
Кстати, теоретически, писать можно непрерывно (главное, чтобы указатель записи не пытался затреть данные, которые чип ещё не успел отправить).
И, в таком случае, kolobok0 будет прав - пакеты определяются передатчиком.
Помнится, когда писал сетевые приложения в Win* - получил странность: при отправке 2-4 мелких пакетов, приходит один, но большой. Долго ломал голову. Оказалось, дело в тех же сокетах и времени.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение May 14 2015, 19:04
Сообщение #16


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(mr_smit @ May 14 2015, 06:26) *
Выходит надо учитывать переменную ret. Это число реально переданных байт..... заголовка к каждой части посылки остается открытым.


1) я пытался обратить Ваше внимание на ПРИЁМ. Т.е. Не факт, что к Вам пришло все 2048 байт!
2) На передаче, если кол-во переданных байт НЕ равно реально переданных - то это ОДНОЗНАЧНО ошибка канала.
Т.е. нехватка памяти, разрыв и т.д..
3) По заголовку странный вопрос. Т.к. его очень просто проверить в любом php каком нить и джэльтменском наборе
писателя вэбовских дел типа дэнвера. И сетевого анализатора. Этого полностью достаточно для детального ковыряния и быстрого
достижения цели(на самом деле хватает ышо меньше - анализатора и любого инет броузера) Если у Вас по логике HTTP уровня
должен отдаваться заголовок - значит да. Если нет - значит нет.
Go to the top of the page
 
+Quote Post
mr_smit
сообщение May 17 2015, 15:52
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 62
Регистрация: 22-07-09
Пользователь №: 51 457



И всё равно я не могу передать изображение sad.gif Взял png изображение размером 2179 байт. Открыл через HEX редактор. Создал массив байт:
Код
const char Img [2179] =
{
0x89,0x50,0x4E,0x47,0x0D...
...
};

И пробую передать по запросу в браузер. В состоянии http_state[sn]==HTTP_IDLE формирую заголовок:
Код
if(strcmp(url,"/test.png")==0)
              {
                strcpy((char*)buf,http_200);
                strcat((char*)buf, http_server);
                strcat((char*)buf,"Connection: close\r\n");
                strcat((char*)buf,"Content-Length: ");
                itoa(sizeof(Img),str);
                strcat((char*)buf,str);
                strcat((char*)buf,"\r\n");
                strcat((char*)buf,"Content-Type: image/png\r\n");
                strcat((char*)buf, http_header_end);
                header_sz=strlen((char*)buf);
                http_state[sn]=HTTP_SENDING;
              }

В состоянии http_state[sn]==HTTP_SENDING отправляю изображение по частям:
Код
if(http_state[sn]==HTTP_SENDING)
         {
             ret = send(sn,buf,header_sz);   // заголовок
             ret = send(sn,&Img[0],2048);    // первые 2048 байт изображения
             ret = send(sn,&Img[2048],130);  // остаток
             HTTP_reset(sn);
             disconnect(sn);
         }

В итоге при обращении по адресу 192.168.1.25/test.png браузер показывает изображение, но только эти первые 2048 байт. Последние байты не отображаются. Т.е. не передаются.
Прикрепленное изображение

Я не понимаю почему так. Хоть убейте. Почему при вызове функции send второй раз она ничего не передает??
Go to the top of the page
 
+Quote Post
AlanDrakes
сообщение May 18 2015, 15:12
Сообщение #18


Частый гость
**

Группа: Участник
Сообщений: 101
Регистрация: 2-05-15
Из: Россия, Омск
Пользователь №: 86 474



Опять же, попробуйте так:
Код
send_bytes: integer;
....
send_bytes = 0;
tmp = send(sn,buf,header_sz);   // заголовок
if (tmp < 0) { break; };  // Если ошибка - выход.
while (send_bytes < sizeof(Img))
{
   tmp = (sizeof(Img) - send_bytes);            // Пытаемся отправить по максимуму
   tmp = send(sn,&Img[send_bytes],2048);    // первые 2048 байт изображения
   if (tmp < 0) { break; }; // Опять же, если ошибка....
   // Если дошли до сюда...
   send_bytes += tmp;
};
...
close(sn);


PS: Рекомендую использовать отладку, чтобы видеть, что происходит.
До закрытия сокета браузер будет пытаться получить картинку - это нормально - он ожидает ответа сервера (а сервер может задуматься).
Если кажется, что код слишком компактно написан - разверните операторные скобки и ставьте точки останова на процедуре выхода (break;).

Сообщение отредактировал AlanDrakes - May 18 2015, 15:15
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 13:19
Рейтинг@Mail.ru


Страница сгенерированна за 0.01584 секунд с 7
ELECTRONIX ©2004-2016