Работа с Ethernet (отследить линк на порту)

alex.vel
alex.vel аватар
Offline
Зарегистрирован: 13.11.2013

В проекте используется библиотека EtherCard http://mk90.blogspot.ru/2013_02_01_archive.html,  и соответственно Ethernet Shield от Arduino на микросхеме Wiznet W5100.

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

Заранее спасибо всем отозвавшимся.)

maksim
Offline
Зарегистрирован: 12.02.2012

alex.vel пишет:

В проекте используется библиотека EtherCard http://mk90.blogspot.ru/2013_02_01_archive.html,  и соответственно Ethernet Shield от Arduino на микросхеме Wiznet W5100.

Библиотека EtherCard не предназначена для W5100. Так что вы для начала определитесь с чем вы работаете с W5100 или с ENC28J60.

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

alex.vel
alex.vel аватар
Offline
Зарегистрирован: 13.11.2013

Библиотека http://arduino.cc/en/Reference/Ethernet - эта, если уточнить.

Собственно мне кажется, что дело не в библиотеке, хотя, конечно же фукции такой ей не хватает.

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

maksim
Offline
Зарегистрирован: 12.02.2012

У W5100 отсутствуют регистры с состоянием светодиодов, которые мигают/горят на шилде, так что остается только паять.

Но вопрос еще остается следующий - а зачем вам это?

alex.vel
alex.vel аватар
Offline
Зарегистрирован: 13.11.2013

Вопрос странный)))) У меня работает телнет клиент, и вполне естественно моё желание знать все ли у меня впорядке со связью. Но в случае элементарного отключения кабеля (особенно если это произошло после успешного подключения) - я ничего, получается, об этом не знаю. Функция connected "молчит", состояние сокета ESTABLISHED, и т.п.

Вот и вопрос: как отследить реальное состояние связи в ран-тайме.

maksim
Offline
Зарегистрирован: 12.02.2012

Да нет вопрос то как раз не странный. Во-первых не всегда причиной отсутствия связи является обрыв провода, а во вторых - почитайте http://www.rsdn.ru/article/net/keep_alive.xml. А вот keepalive у W5100 реализован.

alex.vel
alex.vel аватар
Offline
Зарегистрирован: 13.11.2013

Толчем воду в ступе....

Во-первых: отсутствие связи - это отсутствие связи, не зависимо от причин. Если эту самую причину можно конкретизировать - это великолепно, если нет - не так уж и важно. Главное - ЗНАТЬ ЧТО СВЯЗЬ БЫЛА И ЕЕ НЕ СТАЛО, ИЛИ НЕБЫЛО И НЕТ ЕЁ ВОВСЕ, ИЛИ ПОЯВИЛАСЬ.

Во-вторых: что такое keep-alive я прекрасно знаю, но что/как это реализовано в w5100 не знаю, поэтому и задаю вопрос, на который стараюсь получить конкретный ответ. Если таковой у Вас имеется - будь-те добры, если нет - извольте.

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

ENC28J60 может информировать о линке....

alex.vel
alex.vel аватар
Offline
Зарегистрирован: 13.11.2013

"ENC28J60 может информировать о линке...."(с)

А конкретнее?

maksim
Offline
Зарегистрирован: 12.02.2012

Ну так если знаете о существовании keep-alive и знаете что причин отсутствия связи  множество, то почему сразу нельзя было задаться вопросом как реализовать в библиотеке Ethernet keep-alive ?

alex.vel пишет:

Если таковой у Вас имеется - будь-те добры, если нет - извольте.

А вариант "имеется - извольте" не рассматривается?

В файл w5100.h в enum SockCMD добавляете строку Sock_SEND_KEEP = 0x22, (если отсутствует);
В файл socket.h добавьте строку extern uint8_t keep_alive(SOCKET s);
В файл socket.cpp добавьте:

uint8_t keep_alive(SOCKET s)
{
  W5100.execCmdSn(s, Sock_SEND_KEEP);
  return 1;
}

В файл EthernetClient.h добавьте строку uint8_t keepalive();
В файл EthernetClient.cpp добавьте

uint8_t EthernetClient::keepalive() {
  if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED;
  return keep_alive(_sock);
}

Как пользоваться, думаю разберетесь, если не изменяет память таймаут 30 секунд.

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

В библиотеке EtherCard

можно так

// Demonstrates usage of the new udpServer feature.
//You can register the same function to multiple ports, and multiple functions to the same port.
//
// 2013-4-7 Brian Lee <cybexsoft@hotmail.com>

#include <EtherCard.h>
#include <IPAddress.h>

#define STATIC 0 // set to 1 to disable DHCP (adjust myip/gwip values below)

#if STATIC
// ethernet interface ip address
static byte myip[] = { 192,168,0,200 };
// gateway ip address
static byte gwip[] = { 192,168,0,1 };
#endif

// ethernet mac address - must be unique on your network
static byte mymac[] = { 0x70,0x69,0x69,0x2D,0x30,0x31 };

byte Ethernet::buffer[500]; // tcp/ip send and receive buffer
bool link;

//callback that prints received packets to the serial port
void udpSerialPrint(word port, byte ip[4], const char *data, word len) {
  IPAddress src(ip[0], ip[1], ip[2], ip[3]);
  Serial.println(src);
  Serial.println(port);
  Serial.println(data);
  Serial.println(len);
}

void setup(){
  Serial.begin(57600);
  Serial.println("\n[backSoon]");

  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
    Serial.println( "Failed to access Ethernet controller");
#if STATIC
  ether.staticSetup(myip, gwip);
#else
  if (!ether.dhcpSetup())
    Serial.println("DHCP failed");
#endif

  ether.printIp("IP: ", ether.myip);
  ether.printIp("GW: ", ether.gwip);
  ether.printIp("DNS: ", ether.dnsip);

  //register udpSerialPrint() to port 1337
  ether.udpServerListenOnPort(&udpSerialPrint, 1337);

  //register udpSerialPrint() to port 42.
  ether.udpServerListenOnPort(&udpSerialPrint, 42);
  link = ether.isLinkUp();
}

void loop(){
  if(link != ether.isLinkUp()){
      link = ether.isLinkUp();
      Serial.print("Link is ");
      if(link){
          Serial.println("UP");
      }else{
          Serial.println("DOWN");
      }
  }
  //this must be called for ethercard functions to work.
  ether.packetLoop(ether.packetReceive());
}

Если я правильно понимаю обьединение классов из ENC28J60

alex.vel
alex.vel аватар
Offline
Зарегистрирован: 13.11.2013

Огромное всем спасибо. Завтра проверяю, т.к. девайс не под рукой, и обязательно отпишусь.