Страница 1 из 1

Сервер на WIZnet W5500, отправить изображение

Добавлено: Пн май 11, 2015 10:41:37
mr_smit
Прикупил у китайцев плату с чипом W5500. Это обновленная версия Ethernet чипа W5100. Подключил к STM32 Discovery. За основу взял эту статью: http://we.easyelectronics.ru/GYUR22/w55 ... erver.html. Убрал функции работы с SD картой и с горем пополам скомпилировал всё это в CooCox. Сервер заработал. Т.е. отдает в браузер статичный текст.

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

Код: Выделить всё

<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 редакторе и сделал массив сырых данных:

Код: Выделить всё

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 заголовку приклеиваем сырые данные картинки.
Спойлер

Код: Выделить всё

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;
}
В итоге запрос на картинку в браузере идет, но сервер её не отдает.
Html.png
(101.78 КБ) 730 скачиваний
При этом браузер получает заголовки ответа. Но самого изображения нет.

От безысходности установил HTTP снифер Wireshark. Удалось выяснить, что при передаче картинки сервер отправляет только её первые 8 байт. И на этом всё.
PNG.png
(150.99 КБ) 656 скачиваний
3-й день бьюсь. Не понимаю почему так происходит. Или где то функцию отправки надо изменить или с размером передаваемых данных что то не то. Гуглил и по W5100 и по W5200 и по W5500, но именно как передать изображение не нашел.
web_discovery+w5500_sd.zip
(557.27 КБ) 248 скачиваний
Кто чем может.

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Вс май 17, 2015 18:53:40
mr_smit
И всё равно я не могу передать изображение :( Взял 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 байт. Последние байты не отображаются. Т.е. не передаются.
t.png
(124.35 КБ) 435 скачиваний
Я не понимаю почему так. Хоть убейте. Почему при вызове функции send второй раз она ничего не передает??

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Пн май 18, 2015 12:16:55
BorisSPB
Наверно надо убрать HTTP_reset(sn).

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Сб май 23, 2015 00:09:58
msxfan
mr_smit писал(а):Я не понимаю почему так. Хоть убейте. Почему при вызове функции send второй раз она ничего не передает??
Добрый день. Предлагаю уменьшить размер первой отправки с 2048 до скажем 1024 или даже 512 байт. Попробуйте вместо одного 2048 четыре по 512.

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Сб май 23, 2015 02:17:29
Ser60
Согласно Wireshark, при запросе соединения с Вашим сервером (пакет SYN) Gateway сообщает ему максимальную длину принимаемого собщения 1460 байт (это на данные + 40 байт заголовков TCP и IP), а Вы в него все 2048 данных пихаете.

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Сб май 23, 2015 18:56:39
BorisSPB
1460 - это размер сегмента, размер окна - 2048 байт.

Код: Выделить всё

ret = send(sn,&Img[0],2048);   // первые 2048 байт изображения
заполняет буфер, а следующее обращение

Код: Выделить всё

ret = send(sn,&Img[2048],130);  // остаток
скорее всего возвращает ret=0, т.к. буфер заполнен, а подтверждение еще не пришло.
Надо анализировать возвращаемое значение.

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Пн май 25, 2015 06:48:57
mr_smit
BorisSPB писал(а):

Код: Выделить всё

ret = send(sn,&Img[0],2048);   // первые 2048 байт изображения
заполняет буфер, а следующее обращение

Код: Выделить всё

ret = send(sn,&Img[2048],130);  // остаток
скорее всего возвращает ret=0, т.к. буфер заполнен, а подтверждение еще не пришло.
Надо анализировать возвращаемое значение.
Так функция send возвращает количество реально переданных байт. Пока она не отработает мы на вторую строчку не попадем. Браузер показывает что ровно 2 кБ принял.

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Пн май 25, 2015 10:44:24
BorisSPB
А функция send точно блокирующая?
А то похоже что соединение на уровне приложения закрывается с заполненным под завязку буфером, буфер в фоновом режиме передается и соединение закрывается на уровне TCP.

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Пн май 25, 2015 19:48:59
mr_smit
Это библиотечная функция. Вот что производитель пишет про неё:
/**
* @ingroup WIZnet_socket_APIs
* @brief Send data to the connected peer in TCP socket.
* @details It is used to send outgoing data to the connected socket.
* @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n
* In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n
* In non-block io mode, It return @ref SOCK_BUSY immediatly when socket buffer is not enough. \n
* @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
* @param buf Pointer buffer containing data to be sent.
* @param len The byte length of data in buf.
* @return @b Success : The sent data size \n
* @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
* @ref SOCKERR_TIMEOUT - Timeout occurred \n
* @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
* @ref SOCKERR_SOCKNUM - Invalid socket number \n
* @ref SOCKERR_DATALEN - zero data length \n
* @ref SOCK_BUSY - Socket is busy.
*/
P.S. Чушь какая то:
1_.png
(127.51 КБ) 688 скачиваний
2_.png
(134.42 КБ) 680 скачиваний
Правда я переменную ret сделал глобальной, иначе она в отладчике не отображалась.

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Чт фев 11, 2016 12:41:44
r0cket111
Ну и как результат ? что нибудь получилось ?

Re: Сервер на WIZnet W5500, отправить изображение

Добавлено: Пт фев 12, 2016 21:30:10
mr_smit