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

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение 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 КБ) 733 скачивания
При этом браузер получает заголовки ответа. Но самого изображения нет.

От безысходности установил HTTP снифер Wireshark. Удалось выяснить, что при передаче картинки сервер отправляет только её первые 8 байт. И на этом всё.
PNG.png
(150.99 КБ) 658 скачиваний
3-й день бьюсь. Не понимаю почему так происходит. Или где то функцию отправки надо изменить или с размером передаваемых данных что то не то. Гуглил и по W5100 и по W5200 и по W5500, но именно как передать изображение не нашел.
web_discovery+w5500_sd.zip
(557.27 КБ) 249 скачиваний
Кто чем может.
Нельзя всё знать, достаточно понимать.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение 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 КБ) 437 скачиваний
Я не понимаю почему так. Хоть убейте. Почему при вызове функции send второй раз она ничего не передает??
Нельзя всё знать, достаточно понимать.
Реклама
Встал на лапы
Сообщения: 145
Зарегистрирован: Ср фев 01, 2012 10:55:53

Сообщение BorisSPB »

Наверно надо убрать HTTP_reset(sn).
Встал на лапы
Сообщения: 147
Зарегистрирован: Пн июн 14, 2010 22:32:36
Откуда: Москва

Сообщение msxfan »

mr_smit писал(а):Я не понимаю почему так. Хоть убейте. Почему при вызове функции send второй раз она ничего не передает??
Добрый день. Предлагаю уменьшить размер первой отправки с 2048 до скажем 1024 или даже 512 байт. Попробуйте вместо одного 2048 четыре по 512.
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 3793
Зарегистрирован: Ср дек 24, 2008 09:58:58

Сообщение Ser60 »

Согласно Wireshark, при запросе соединения с Вашим сервером (пакет SYN) Gateway сообщает ему максимальную длину принимаемого собщения 1460 байт (это на данные + 40 байт заголовков TCP и IP), а Вы в него все 2048 данных пихаете.
Реклама
Встал на лапы
Сообщения: 145
Зарегистрирован: Ср фев 01, 2012 10:55:53

Сообщение BorisSPB »

1460 - это размер сегмента, размер окна - 2048 байт.

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

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

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

ret = send(sn,&Img[2048],130);  // остаток
скорее всего возвращает ret=0, т.к. буфер заполнен, а подтверждение еще не пришло.
Надо анализировать возвращаемое значение.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

BorisSPB писал(а):

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

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

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

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

Сообщение BorisSPB »

А функция send точно блокирующая?
А то похоже что соединение на уровне приложения закрывается с заполненным под завязку буфером, буфер в фоновом режиме передается и соединение закрывается на уровне TCP.
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение 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 КБ) 690 скачиваний
2_.png
(134.42 КБ) 683 скачивания
Правда я переменную ret сделал глобальной, иначе она в отладчике не отображалась.
Нельзя всё знать, достаточно понимать.
Родился
Сообщения: 9
Зарегистрирован: Пт дек 13, 2013 18:37:51

Сообщение r0cket111 »

Ну и как результат ? что нибудь получилось ?
Вымогатель припоя
Аватара пользователя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

Нельзя всё знать, достаточно понимать.
Ответить

Вернуться в «ARM»