Создание 2 клиентов TCP

использую библиотеку Ethernet.h
объявил двух клиентов
Код (C++):

EthernetClient clientcentral;
EthernetClient clientwork;

подключаю через
Код (C++):

if (clientcentral.connect(mainip, mainPort))
     Serial.println("connected to central");
if (clientwork.connect(deip, dePort))
     Serial.println("connected to work");

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

В исходник библиотеки заглядывали? Может она так написана, что позволяет запускать только один экземпляр клиента одновременно.

заметил такую штуку: если ардуину перезапустить, то clientcentral подключается, как надо, а clientwork - нет. Если перезапустить приложение на компе, то уже оба сразу подключаются. И так, пока не перезапустишь ардуину.
т.е., при новом запуске проекта, она, вроде как, нормально работает, пока не закроешь и не откроешь заново источник подключения.

Думаю, что ошибка в 47-ой строке скетча.

В исходник библиотеки заглядывали? Может она так написана, что позволяет запускать только один экземпляр клиента одновременно.

я не спец по исходникам, к сожалению.

Но как то же ты их пишешь, хоть и “не спец”…

я не понимаю логики исходников

Печально.

Но в этой-то теме чего Вы от нас ждёте? Чем Вас мой ответ выше не устраивает?

а в 48 вас разве всё устраивает?

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

Я туда не добрался. Увидел в №47, решил, что сначала надо это исправить.

согласен!

если есть, чем помочь - жду помощи.

если вы ждете помощи по коду - то хотя бы стоит его выложить на форум, нет?

правильно ли я мыслю.
у меня клиент подключается через данный код библиотеки.
в ней был 0 вместо номера порта подключения

Ethernet.socketConnect(sockindex, rawIPAddress(ip), 0);

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

int EthernetClient::connect(IPAddress ip, uint16_t port)
{
	if (sockindex < MAX_SOCK_NUM) {
		if (Ethernet.socketStatus(sockindex) != SnSR::CLOSED) {
			Ethernet.socketDisconnect(sockindex); // TODO: should we call stop()?
		}
		sockindex = MAX_SOCK_NUM;
	}
#if defined(ESP8266) || defined(ESP32)
	if (ip == IPAddress((uint32_t)0) || ip == IPAddress(0xFFFFFFFFul)) return 0;
#else
	if (ip == IPAddress(0ul) || ip == IPAddress(0xFFFFFFFFul)) return 0;
#endif
	sockindex = Ethernet.socketBegin(SnMR::TCP, port);
	if (sockindex >= MAX_SOCK_NUM) return 0;
	Ethernet.socketConnect(sockindex, rawIPAddress(ip), port);
	uint32_t start = millis();
	while (1) {
		uint8_t stat = Ethernet.socketStatus(sockindex);
		if (stat == SnSR::ESTABLISHED) return 1;
		if (stat == SnSR::CLOSE_WAIT) return 1;
		if (stat == SnSR::CLOSED) return 0;
		if (millis() - start > _timeout) break;
		delay(1);
	}
	Ethernet.socketClose(sockindex);
	sockindex = MAX_SOCK_NUM;
	return 0;
}

далее все пришло к данному коду

uint8_t EthernetClass::socketBegin(uint8_t protocol, uint16_t port)
{
	uint8_t s, status[MAX_SOCK_NUM], chip, maxindex=MAX_SOCK_NUM;

	// first check hardware compatibility
	chip = W5100.getChip();
	if (!chip) return MAX_SOCK_NUM; // immediate error if no hardware detected
#if MAX_SOCK_NUM > 4
	if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets
#endif
	//Serial.printf("W5000socket begin, protocol=%d, port=%d\n", protocol, port);
	SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
	// look at all the hardware sockets, use any that are closed (unused)
	for (s=0; s < maxindex; s++) {
		status[s] = W5100.readSnSR(s);
		if (status[s] == SnSR::CLOSED) goto makesocket;
	}
	//Serial.printf("W5000socket step2\n");
	// as a last resort, forcibly close any already closing
	for (s=0; s < maxindex; s++) {
		uint8_t stat = status[s];
		if (stat == SnSR::LAST_ACK) goto closemakesocket;
		if (stat == SnSR::TIME_WAIT) goto closemakesocket;
		if (stat == SnSR::FIN_WAIT) goto closemakesocket;
		if (stat == SnSR::CLOSING) goto closemakesocket;
	}
#if 0
	Serial.printf("W5000socket step3\n");
	// next, use any that are effectively closed
	for (s=0; s < MAX_SOCK_NUM; s++) {
		uint8_t stat = status[s];
		// TODO: this also needs to check if no more data
		if (stat == SnSR::CLOSE_WAIT) goto closemakesocket;
	}
#endif
	SPI.endTransaction();
	return MAX_SOCK_NUM; // all sockets are in use
closemakesocket:
	//Serial.printf("W5000socket close\n");
	W5100.execCmdSn(s, Sock_CLOSE);
makesocket:
	//Serial.printf("W5000socket %d\n", s);
	EthernetServer::server_port[s] = 0;
	delayMicroseconds(250); // TODO: is this needed??
	W5100.writeSnMR(s, protocol);
	W5100.writeSnIR(s, 0xFF);
	if (port > 0) {
		W5100.writeSnPORT(s, port);
	} else {
		// if don't set the source port, set local_port number.
		if (++local_port < 49152) local_port = 49152;
		W5100.writeSnPORT(s, local_port);
	}
	W5100.execCmdSn(s, Sock_OPEN);
	state[s].RX_RSR = 0;
	state[s].RX_RD  = W5100.readSnRX_RD(s); // always zero?
	state[s].RX_inc = 0;
	state[s].TX_FSR = 0;
	//Serial.printf("W5000socket prot=%d, RX_RD=%d\n", W5100.readSnMR(s), state[s].RX_RD);
	SPI.endTransaction();
	return s;
}

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

if (linkstate != 1)
  {
      Serial.println("сетевой кабель не подключен");
  }
  else
  {
      digitalWrite(ledPin, digitalRead(ledPin) ^ 1);  //включаем и выключаем светодиод
      if (clientcentral.connected())
      {
        Serial.println("central подключен"); 
        //Serial.println(client[0].rawIPAddress);
      }        
      if (clientwork.connected())
        Serial.println("work подключен"); 
        
      if (CentralConnect)
      {
          unsigned long t1 = millis();
          CentralConnect = false;
          if (!clientcentral.connected())
          {    
              //Serial.println("подключаю central");
              clientcentral.connect(mainip, mainPort);
              delay(50);
              /*if (clientcentral.connected())
              {
                  Serial.println("connected to central");
                  Serial.println("проверка централ1 " + String(mainPort));
                  Serial.println("проверка централ2 " + String(clientcentral.remotePort()));
                  if (clientcentral.remotePort() != mainPort)
                  {
                      clientcentral.stop();
                      Serial.println("остановил central");
                  }
                  else
                  {
                      Serial.println("оставил central");
                  }
                  Serial.println("проверка ворк1 " + String(dePort));
                  Serial.println("проверка ворк2 " + String(clientwork.remotePort()));
                  if (clientwork.connected())
                  {    
                      if (clientwork.remotePort() != dePort)
                      {
                          clientwork.stop();
                          Serial.println("отключил ворк");
                      } 
                  }
              } */ 
              if (clientcentral.connected()) {
                  Serial.println("connected to central");
                  KolGo == 0;
              } else {
                  for (byte i = 0; i < 4; i++)
                  {
                    Serial.print(mainip[i]);
                    if (i < 3)
                      Serial.print(".");
                    else
                      Serial.print(":");
                  }
                  Serial.print(mainPort);
                  Serial.println(" connection central failed");
              }
          }
          if (clientcentral.connected())
          {
              
              byte buf[12] = {0};
              buf[0] = 34;
              for (byte i = 1; i < 7; i++)
              {
                buf[i] = mac[i - 1];
              }
              buf[7] = DeviceType;
              buf[8] = 47;
              buf[9] = 101;
              buf[10] = 110;
              buf[11] = 100;
              clientcentral.write(buf, 12);
            /* for (int i = 0; i < 7; i++)
              {
                Serial.print(mac[i], HEX);
                if (i < 6)
                  Serial.print(",");
                else  
                  Serial.println(); 
              } */
              /*for (int i = 0; i < 7; i++)
              {
                Serial.print(mac[i]);
                if (i < 6)
                  Serial.print(",");
                else  
                  Serial.println(); 
              } */  
              for (byte i = 0; i < 4; i++)
              {
                Serial.print(myip[i]);
                if (i < 3)
                  Serial.print(".");
                else
                  Serial.print(":");
              }
              Serial.print(myPort);
              Serial.println(" Отправил пинг central");
          }
          unsigned long t2 = millis();
          unsigned long r = t2 - t1;
          Serial.print(t1);
          Serial.print("-");
          Serial.println(t2);
          Serial.println(r);
      }
      else
      {   
          unsigned long t1 = millis();
          CentralConnect = true;
          if (!clientwork.connected())
          {    
              clientwork.connect(deip, dePort);
              delay(50);
              if (clientwork.connected()) {
                  Serial.println("connected to work");
                  KolGo == 0;
              } else {
                  for (byte i = 0; i < 4; i++)
                  {
                    Serial.print(deip[i]);
                    if (i < 3)
                      Serial.print(".");
                    else
                      Serial.print(":");
                  }
                  Serial.print(dePort);
                  Serial.println(" connection work failed");
              }
          }      
          if (clientwork.connected())
          {
              byte buf[12] = {0};
              buf[0] = 34;
              for (byte i = 1; i < 7; i++)
              {
                buf[i] = mac[i - 1];
              }
              buf[7] = DeviceType;
              buf[8] = 47;
              buf[9] = 101;
              buf[10] = 110;
              buf[11] = 100;
              clientwork.write(buf, 12);
              for (byte i = 0; i < 4; i++)
              {
                Serial.print(myip[i]);
                if (i < 3)
                  Serial.print(".");
                else
                  Serial.print(":");
              }
              Serial.print(myPort);
              Serial.println(" Отправил пинг work");
          }
          unsigned long t2 = millis(); 
          int r = t2 - t1;
          Serial.println(r);
      }
      
    }
    digitalWrite(ledPin, digitalRead(ledPin) ^ 1);  //включаем и выключаем светодиод
}

логика такова, что поочередно опрашивается соединение, и если клиент не соединен, то происходит попытка соединиться.
в начале процесса загорается светодиод 13, а в конце процесса - гаснет.
еще вчера заметил, следующее:
в первой части соединения (клиентцентрал) сетодиод горит гораздо меньше по времени, чем во время второго круга (клиентворк), хотя код подключения и там и там одинаков. пытался посчитать в миллисекундах - не получилось

Ты прав, этот код

опять ворчишь? помогай, давай…

Вот и смоделируйте его и выложите на форум законченный тестовый код, который каждый сможет загрузить себе и хотя бы скомпилировать…
Разбираться в обрывках кода то себе удовольствие.

1 лайк