Выполнение http запроса Ethernet.h

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Здравствуйте)))

 if (client.connect(server, 80)) {
    Serial.println("connected");  //  "Подключение установлено" 
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  } else {
    // Если соединения с сервером нет, пишем об этом на Serial Monitor:
    Serial.println("connection failed");  //  "Подключиться не удалось"
  }
}

Мне нужно постоянно отправлять данные на сервер. Я могу это делать через каждые 500 мс и данные успешно отправляются, а я хочу чтобы следующий пакет данных отправился после подтверждения отправки предыдущих.

Т.е. если запрос успешно отправился, выполняем следующий и т д.

Как организовать?

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

А смысл? TCP сам по себе гарантирует целостность данных. Или в чем суть?

Logik
Offline
Зарегистрирован: 05.08.2014

это ddos кому то делаете?

sadman41
Offline
Зарегистрирован: 19.10.2016

Подтверждения чем - собесом, счётной палатой, кошачьим хвостом?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Rumata пишет:

А смысл? TCP сам по себе гарантирует целостность данных. Или в чем суть?

void loop() {
 if (client.connect(server, 80)) {
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: <a href="123" title="456"" rel="nofollow">789"</a>);
    client.println("Connection: close");
    client.println();
  }
}  

Т.е. следующий запрос произойдет сразу после предыдущего? Не получится что первый запрос еще не выполнился, а я уже следующий отправляю?

Цитата:

это ddos кому то делаете?

Нет)))

Цитата:

Подтверждения чем - собесом, счётной палатой, кошачьим хвостом?

Последний вариант, думаю)

А по факту, произошла отправка, если сервер ответил 200 OK, отправляю дальше, но как я поняла это лишнее, сервер локальный.

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Ответ 200 OK говорит только о том, что состоялся прием данных веб-сервером, но не обязательно о том, что произошла их обработка (
https://developer.mozilla.org/ru/docs/Web/HTTP/Status/200 )
Т.е. 200 ОК может возвращаться вместе с SQL Error в теле ответа, к примеру. Поэтому вопрос "что является подтверждением и кто его выдает?" - ключевой в данной ситуации. Весь дальнейший алгоритм проистекает из ответа.

vde69
Offline
Зарегистрирован: 10.01.2016

HTTP предусматривает внутри себя

1. паралельную доставку пакетов (пришло половина пакета 1 потом пакет 2 а потом вторая половина пакета 1)

2. контроль всего этого дела

 

реальный таймаут ожидания может быть довольно большим (абсолютно реально до 5 сек), ставя 0.5сек ты идешь в разрез с этим протоколом.

если тебе надо быстрый обмен - переходи на другие протоколы, на HTTP делать твою хотелку - просто бесмыслено...

vde69
Offline
Зарегистрирован: 10.01.2016
negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

vde69 пишет:

HTTP предусматривает внутри себя

1. паралельную доставку пакетов (пришло половина пакета 1 потом пакет 2 а потом вторая половина пакета 1)

2. контроль всего этого дела

O_O фигасе новинки в HTTP.

vde69
Offline
Зарегистрирован: 10.01.2016

negavoid2 пишет:

vde69 пишет:

HTTP предусматривает внутри себя

1. паралельную доставку пакетов (пришло половина пакета 1 потом пакет 2 а потом вторая половина пакета 1)

2. контроль всего этого дела

O_O фигасе новинки в HTTP.

разумеется это не сам HTTP, я написал с упрощениями, иначе придется расписывать отличия UDP от TCP

sadman41
Offline
Зарегистрирован: 19.10.2016

HTTP собирает пакеты? С IP не путаете?

https://ru.wikipedia.org/wiki/HTTP#GET

----
С помощью метода GET можно также начать какой-либо процесс. В этом случае в тело ответного сообщения следует включить информацию о ходе выполнения процесса.
----

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

подпишусь

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Вопрос 

    client.println("POST /temp.php HTTP/1.1");
    client.println("Host: 192.168.0.22");
    client.println("Content-Length: 8");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("");
    client.println("cat=1233");
    client.println("Connection: close");
    client.println();

php

$cat=$_POST['cat'];
echo ($cat);
echo ("OK");
?>

Ардуинка печатает следующее:

connected
HTTP/1.1 200 OK

Date: Sat, 27 Mar 2021 19:34:35 GMT

Server: Apache

Cache-Control: no-store, no-cache, must-revalidate

Content-Length: 9

Content-Type: text/html



1233OKHTTP/1.1 400 Bad Request

Date: Sat, 27 Mar 2021 19:34:35 GMT

Server: Apache

Vary: accept-language,accept-charset

Accept-Ranges: bytes

Connection: close

Content-Type: text/html; charset=utf-8

Content-Language: en

Expires: Sat, 27 Mar 2021 19:34:35 GMT



<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

<head>

<title>Bad request!</title>

<link rev="made" href="mailto:%5bno%20address%20given%5d" />

<style type="text/css"><!--/*--><![CDATA[/*><!--*/ 

    body { color: #000000; background-color: #FFFFFF; }

    a:link { color: #0000CC; }

    p, address {margin-left: 3em;}

    span {font-size: smaller;}

/*]]>*/--></style>

</head>



<body>

<h1>Bad request!</h1>

<p>





    Your browser (or proxy) sent a request that

    this server could not understand.



</p>

<p>

If you think this is a server error, please contact

the <a href="mailto:%5bno%20address%20given%5d">webmaster</a>.



</p>



<h2>Error 400</h2>

<address>

  <a href="/">default</a><br />

  <span>Apache</span>

</address>

</body>

</html>

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Откуда берется HTTP/1.1 400 Bad Request

sadman41
Offline
Зарегистрирован: 19.10.2016

https://developer.mozilla.org/ru/docs/Web/HTTP/Methods/POST
Обратите внимание на "Пример". Там пустая строка между хидером и телом. Насколько я помню - в RFC должно быть двойное \r\n , а println() даёт только \n

Я бы вам посоветовал простой путь, если не хотите по стандартам ползать - подсмотреть обмен между браузером и веб-сервером Wireshark-ом, а потом имитировать "через ардуину".

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020
client.println("POST /temp.php HTTP/1.1");
client.println("Host: 192.168.0.22");
client.println("Content-Length: 8");
client.println("Content-Type: application/x-www-form-urlencoded");
client.println("");
client.print("cat=1233");

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

negavoid2 пишет:

client.println("POST /temp.php HTTP/1.1");
client.println("Host: 192.168.0.22");
client.println("Content-Length: 8");
client.println("Content-Type: application/x-www-form-urlencoded");
client.println("");
client.print("cat=1233");

 

 

Так работает, получаю

1233QAZHTTP/1.1 200 OK

Date: Sat, 27 Mar 2021 19:57:46 GMT

Server: Apache

Cache-Control: no-store, no-cache, must-revalidate

Content-Length: 10

Content-Type: text/html



 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

А если я не знаю число отправляемых байт, как посчитать?

    client.println("POST /temp.php HTTP/1.1");
    client.println("Host: 192.168.0.22");
    client.println("Content-Length: ***");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("");
   for (int i = 1; i < 3; i++) {
      client.print("cat");
      client.print(i);
      client.print("=");
      client.print(analogRead(i));
      client.print("&");
    }

 

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Так и подсчитать. Сперва получить данные, потом сформировать запрос, и только потом отправлять, а считывать данные прямо в процессе отправки запроса считается дурным тоном.

String s;

for (int i = 1; i < 3; i++) {
   s += "cat";
   s += String(i);
   s += "=";
   s += String(analogRead(i));
   // ... что-то типа того
 }

 client.println("POST /temp.php HTTP/1.1");
 client.println("Host: 192.168.0.22");
 client.println("Content-Length: " + String(s.length()) );
 client.println("Content-Type: application/x-www-form-urlencoded");
 client.println("");
 client.print(s);

ps приведённый пример псевдокод, может даже и не скомпилируется, но суть вот такая

sadman41
Offline
Зарегистрирован: 19.10.2016

Я snprintf_P()-ом считаю.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Спасибо.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

vde69 пишет:

если тебе надо быстрый обмен - переходи на другие протоколы, на HTTP делать твою хотелку - просто бесмыслено...

какие протоколы?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

любой tcp/IP или UDP, хоть сами обмен пишите, и сервер и клиента.
Что такое протокол если тупо попроще - просто сбор неких правил и определений, которым должно следовать устройства обмена.
Вы главное не забудьте: если устройства будут обмениваться через какие либо общественные роутеры или интернет - многие не будут пропускать ваш доморощенный протокол. Но если очень хочется - ничего не мешает имитировать http , но обрабатывать заголовки/данные самостоятельно, тогда этому протоколу везде будет дорога по 80 порту.
 

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

andycat пишет:
если устройства будут обмениваться через какие либо общественные роутеры или интернет - многие не будут пропускать ваш доморощенный протокол

С чего бы это такая самодеятельность? Есть tcp пакет, есть udp пакет, на любой (почти) порт - дело провайдера не фильтровать, а пропускать (я в курсе про блок 53/udp вниз у многих, но и причина есть, ну или там 25/tcp). И это последнемильники, а транзитникам вообще пофигу, чем больше трафика, тем лучше. За 20 лет только один раз столкнулся, мобильный провайдер (и опять оконечник bras) резал GRE, причём это была их чёткая позиция, с чем связано, не сказали. Что ж, отдали деньги другому провайдеру.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

negavoid2 пишет:

С чего бы это такая самодеятельность? 

из личного опыта :)
и интернет трафик не только через провайдеров идет, вы можете запустить клиентскую часть своего устройства например в wifi сети некой организации, а там любят все запрещать (сам такой).

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

А, ну там пусть запрещают, их трудности.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Почему ардуино нано (с загрузчиком уно) не видит модуль при таком подключении?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Разобралась, на модуле ICSP  не разведено на пины (11,12,13)

Подключила ICSP модуля к пинам ардуино, и плюс 10 пин.

sadman41
Offline
Зарегистрирован: 19.10.2016

Как это? На ICSP не разведен SPI?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

На Ethernet shield контакты 11 12 и 13 не соединены с ICSP

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192, 168, 0, 56};
byte gateway[] = {192, 168, 0, 1};
byte subnet[] = {255, 255, 255, 0};
byte dns[] = {192, 168, 0, 1};

EthernetClient client;
IPAddress server(192, 168, 0, 2);

А почему у меня плата с такими параметрами работает только через роутер, напрямую с ПК не работает

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Irinka пишет:

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192, 168, 0, 56};
byte gateway[] = {192, 168, 0, 1};
byte subnet[] = {255, 255, 255, 0};
byte dns[] = {192, 168, 0, 1};

EthernetClient client;
IPAddress server(192, 168, 0, 2);

А почему у меня плата с такими параметрами работает только через роутер, напрямую с ПК не работает

видимо надо включить кроссоверным кабелем

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Второй вариант?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

да

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

А на пк-то сетевая карта, куда втыкаете, настроена, как полагается? Кроссоверные кабеля не нужны лет 10-15 как.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Кросоверный вариант не работает.

Сетевая карта настроена как

Проткол интернета Версия 4

192.168.0.55

255.255.255.0

192.168.0.1

 

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Эмм, и вы вытыкаете из неё кабель, ведущий к роутеру, и вместо него втыкаете кабель, ведущий к ардуине?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Кабель от модуля к сетевой карте ПК не работает

Кабель от модуля в роутер, ПК подключен к роутеру - работает

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

странно, должен работать, проверьте чтоб на ПК статический IP стоял, ну и кабель сетевым тестером перепроверить.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Адрес стоит статический. Кабель исправный, через роутер же работает, но проверяла и другой кабель.

Модуль Пингуется

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Да, должно работать. Может, на модуле надо вот это:

IPAddress server(192, 168, 0, 55);

Ну и если вы используете обращение не по ip, а по домену, то не сработает, dns и шлюза нет.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192, 168, 1, 3};
byte gateway[] = {192, 168, 1, 1};
byte subnet[] = {255, 255, 255, 0};
byte dns[] = {192, 168, 1, 1};

EthernetClient client;
IPAddress server(192, 168, 1, 55);
uint32_t Time;


void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac, ip, dns, gateway, subnet);
  Serial.println("Start");
}







void getwww() {

  if (client.connect(server, 80)) {

    client.print("GET /script/php/readsuser.php?r=123&s=456&n=789");
    client.print(" HTTP/1.1");
    client.println();
    client.println("Host: 192.168.1.55");
    client.println("Connection: close");
    client.println();
    //client.stop(); 
Serial.println("OK");

  } else {
    client.stop();
    Serial.println("connection failed");
  }
}











void loop() {
  if (millis() - Time >= 5000) {

    Time = millis();
    getwww()
  }
}//loop

Получаю connection failed

Черезе роутер ОК

Подсеть 192,168,1 , а не 192.168.0  все верно, перешла на другую машину

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

так у пк ip всё же 192.168.0.55 или 192.168.1.55? У ардуины 0 или 1? Должны быть одинаковыми 0/1 и там, и там.

Но вообще, поидее должно работать. Может, конечно, модулю плохеет без шлюза, но сомнительно.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

У ПК адрес 192.168.1.55

У модуля 192.168.1.3

Не успела отредактировать своё сообщение до вашего ответа

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Вижу. Поидее должно работать. Ещё, может быть, фаервол на пк закрывает доступ к серверу.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Тогда бы и через роутер не работало

sadman41
Offline
Зарегистрирован: 19.10.2016

Если часто меняете IP, не меняя MAC, то проблемы сильновероятны, так как ARP-кэш на сторонних устройствах сразу самостоятельно не чистится.

Все эти метания сводят с ума пользователя - то работает сеть, то нет... Меняете IP на Wiznet, меняйте и MAC.

...это не к данной проблеме относится, а вообще.

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

да, хорошая идея. Или arp -d на пк, а модулю просто ребут.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Добавила проверку

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192, 168, 1, 3};
byte gateway[] = {192, 168, 1, 1};
byte subnet[] = {255, 255, 255, 0};
byte dns[] = {192, 168, 1, 1};

EthernetClient client;
IPAddress server(192, 168, 1, 55);
//char server[] = "192, 168, 1, 55"; 
uint32_t Time;

void setup() {
  Serial.begin(9600);
  Time=millis();
  // start the Ethernet connection:
  Serial.println("Initialize Ethernet with DHCP:");
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
      while (true) {
        delay(1); // do nothing, no point running without Ethernet hardware
      }
    }
    if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }
    // try to congifure using IP address instead of DHCP:
   Ethernet.begin(mac, ip, dns, gateway, subnet);
  } else {
    Serial.print("  DHCP assigned IP ");
    Serial.println(Ethernet.localIP());
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.print("connecting to ");
  Serial.print(server);
  Serial.println("...");
}

 

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

При прямом подключении пк <--> wiznet никакого dhcp не будет.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

При подключении через роутер:

Initialize Ethernet with DHCP:

 DHCP assigned IP  192.168.1.56

connecting to 192.168.1.55

при подключении напрямую

Initialize Ethernet with DHCP: