Multiple EthernetServers on different ports

This works (and is supported by one reply in the forum, though I cannot REfind it):

EthernetServer TcpServer0 = EthernetServer(BASE_PORT + 0);
EthernetServer TcpServer1 = EthernetServer(BASE_PORT + 1);
EthernetServer TcpServer2 = EthernetServer(BASE_PORT + 2);
EthernetServer TcpServer3 = EthernetServer(BASE_PORT + 3);

This does not:

EthernetServer TcpServer[4];

EthernetServer TcpServer[0] = EthernetServer(BASE_PORT + 0);
EthernetServer TcpServer[1] = EthernetServer(BASE_PORT + 1);
EthernetServer TcpServer[2] = EthernetServer(BASE_PORT + 2);
EthernetServer TcpServer[3] = EthernetServer(BASE_PORT + 3);

The error message is "... error: no matching function for call to 'EthernetServer::EthernetServer()'"

EthernetServer TcpServer[4];

This defines an array of 4 objects. The objects are instances of the EthernetServer class. The no-argument constructor (there is not one) is called.

EthernetServer TcpServer[0] = EthernetServer(BASE_PORT + 0);
EthernetServer TcpServer[1] = EthernetServer(BASE_PORT + 1);
EthernetServer TcpServer[2] = EthernetServer(BASE_PORT + 2);
EthernetServer TcpServer[3] = EthernetServer(BASE_PORT + 3);

These define 4 more arrays, of various sizes, all named the same thing.

EthernetServer TcpServer[4] = {
        EthernetServer(BASE_PORT + 0),
        EthernetServer(BASE_PORT + 1),
        EthernetServer(BASE_PORT + 2),
        EthernetServer(BASE_PORT + 3) };

Thanks. This compiles. Now working other issues before testing. I am trying to get to a system that can switch between TCP and UDP. If I am running normally under EthernetUDP, can I "switch" to TCP by just executing a normal startup beginning with EthernetServer.begin()? Likewise, can I go from TCP to UDP beginning with EthernetUDP.begin?

You should not have to "switch". Just initialize both. UDP operates on a specific TCP port, so will not interfere with anything else, as long as there is not conflict on port assignment.

Regards,
Ray L.

Thanks for the speedy reply. Assuming all the correct includes and other code that works in a TCP only or UDP only app, is the following what you have in mind?

#define SERVER_MAX   4
#define BASE_PORT    2000

EthernetServer TcpServer[SERVER_MAX] = {0, 0, 0, 0};
EthernetUDP UdpServer[SERVER_MAX];

void setup()
{
	int i;
	
	for (i = 0; i < SERVER_MAX; i++)
	{
		TcpServer[i] = EthernetServer(BASE_PORT + i);
		TcpServer[i].begin();
		UdpServer[i].begin(BASE_PORT + SERVER_MAX + i);
	}
}

You can't start 4 tcp servers & 4 UDP sockets unless you have a w5200.

Thanks. I think I have what I need to experiment. Will post anything new.

This allows me to switch between TCP and UDP. If anyone is interested, please offer comments.

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

#define SERVER_MAX					4
#define BASE_PORT					2000
#define TCP_UDP_CLIENT_CONNECT_TIMEOUT	60

enum TCPUDP_STATE
{
	TCPUDPSidle = 0,
	TCPUDPStcpNext,
	TCPUDPStcp,
	TCPUDPSudpNext,
	TCPUDPSudp
};

byte MACAddr[] = {0x02, 0x00, 0x00, 0x01, 0x00, 0x00};
IPAddress IPAddr(192, 168, 1, 150);
IPAddress GatewayAddr(192, 168, 1, 1);
IPAddress SubnetAddr(255, 255, 0, 0);

unsigned long int uliLoopCount, uliTime100, uliTime1000, uliStartTime;

EthernetServer TcpServer[SERVER_MAX] = {0, 0, 0, 0};
unsigned int TcpClientConnectTimeout[SERVER_MAX] = {0, 0, 0, 0};

char cPacketBuffer[UDP_TX_PACKET_MAX_SIZE];

EthernetUDP UdpServer[SERVER_MAX];
unsigned int UdpClientConnectTimeout[SERVER_MAX] = {0, 0, 0, 0};

enum TCPUDP_STATE TcpUdpState = TCPUDPSidle;

void setup()
{
	int i;
	
	Serial3.begin(115200);
	
	Serial3.println("\r\nTCP UDP Test: TCPUDPSendReceive");
	
	Serial3.print("MAC:  ");
	for (i = 0; i < 6; i++)
	{
		Serial3.print(" ");
		Serial3.print(MACAddr[i], HEX);
	}
	Serial3.println();
	
	Serial3.print("IP:    ");
	Serial3.println(IPAddr);
	
	Serial3.print("Gate:  ");
	Serial3.println(GatewayAddr);
	
	Serial3.print("Sub:   ");
	Serial3.println(SubnetAddr);
	
	Serial3.print("Ports:");
	
	for (i = 0; i < SERVER_MAX; i++)
	{
		Serial3.print(" ");
		Serial3.print((BASE_PORT + i), DEC);
	}
	Serial3.println();
	
	uliStartTime = millis();
	uliTime100 = uliStartTime + 100;
	uliTime1000 = uliStartTime + 1000;
	uliLoopCount = 0;
	
	TcpUdpState = TCPUDPSidle;
}
	
void loop()
{
	byte b;
	char cTcpUdpNextState = 0, str[100];
	int i, iTcpServer, iUdpServer, iPacketSize;
	unsigned long int uliTime;
	
	EthernetClient TcpClient;
	
	uliLoopCount++;
	uliTime = millis();
	
	if (Serial3.available())
	{
		cTcpUdpNextState = Serial3.read();

		Serial3.write('[');
		Serial3.write(cTcpUdpNextState);
		Serial3.write(']');
	}
	
	switch (TcpUdpState)
	{
		
	case TCPUDPSidle:
		if ((cTcpUdpNextState == 'T') || (cTcpUdpNextState == 't'))
		{
			TcpUdpState = TCPUDPStcpNext;
		}
		if ((cTcpUdpNextState == 'U') || (cTcpUdpNextState == 'u'))
		{
			TcpUdpState = TCPUDPSudpNext;
		}
		break;

	case TCPUDPStcpNext:
		Ethernet.begin(MACAddr, IPAddr, GatewayAddr, SubnetAddr);
		for (iTcpServer = 0; iTcpServer < SERVER_MAX; iTcpServer++)
		{
			TcpServer[iTcpServer] = EthernetServer(BASE_PORT + iTcpServer);
			TcpServer[iTcpServer].begin();
			TcpClientConnectTimeout[iTcpServer] = TCP_UDP_CLIENT_CONNECT_TIMEOUT;
		}
		TcpUdpState = TCPUDPStcp;
		break;

	case TCPUDPStcp:
		if ((cTcpUdpNextState == 'U') || (cTcpUdpNextState == 'u'))
		{
			for (iTcpServer = 0; iTcpServer < SERVER_MAX; iTcpServer++)
			{
				TcpClient = TcpServer[iTcpServer].available();
				TcpClient.stop();
			}
			TcpUdpState = TCPUDPSudpNext;
		}
		break;

	case TCPUDPSudpNext:
		Ethernet.begin(MACAddr, IPAddr, GatewayAddr, SubnetAddr);
		for (iUdpServer = 0; iUdpServer < SERVER_MAX; iUdpServer++)
		{
			UdpServer[iUdpServer].begin(BASE_PORT + iUdpServer);
			UdpClientConnectTimeout[iUdpServer] = TCP_UDP_CLIENT_CONNECT_TIMEOUT;
		}
		TcpUdpState = TCPUDPSudp;
		break;

	case TCPUDPSudp:
		if ((cTcpUdpNextState == 'T') || (cTcpUdpNextState == 't'))
		{
			for (iUdpServer = 0; iUdpServer < SERVER_MAX; iUdpServer++)
			{
				UdpServer[iUdpServer].stop();
			}
			TcpUdpState = TCPUDPStcpNext;
		}
		break;
	}
	
	if (uliTime > uliTime1000)
	{
		uliTime1000 += 1000;
		
		sprintf(str, "%10ld %6ld", (uliTime1000 - uliStartTime), uliLoopCount);
		uliLoopCount = 0;
		
		if (TcpUdpState == TCPUDPSidle)
		{
			Serial3.write('I');
		}
		
		else if (TcpUdpState == TCPUDPStcp)
		{
			Serial3.write('T');
		
			if (TcpClientConnectTimeout[0] < TCP_UDP_CLIENT_CONNECT_TIMEOUT)
			{
				TcpClientConnectTimeout[0]++;
				Serial3.write('0');
				TcpServer[0].write(str);
				TcpServer[0].write(" 0: ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n");
			}
			
			if (TcpClientConnectTimeout[1] < TCP_UDP_CLIENT_CONNECT_TIMEOUT)
			{
				TcpClientConnectTimeout[1]++;
				Serial3.write('1');
				TcpServer[1].write(str);
				TcpServer[1].write(" 1: abcdefghijklmnopqrstuvwxyz\r\n");
			}
			
			if (TcpClientConnectTimeout[2] < TCP_UDP_CLIENT_CONNECT_TIMEOUT)
			{
				TcpClientConnectTimeout[2]++;
				Serial3.write('2');
				TcpServer[2].write(str);
				TcpServer[2].write(" 2: !@#$%^&*()_+1234567890-={[}]|:;?/>.<,\r\n");
			}
			
			if (TcpClientConnectTimeout[3] < TCP_UDP_CLIENT_CONNECT_TIMEOUT)
			{
				TcpClientConnectTimeout[3]++;
				Serial3.write('3');
				TcpServer[3].write(str);
				TcpServer[3].write(" 3: !@#$%^&*()_+1234567890-={[}]|:;?/>.<,\r\n");
			}
		}
		
		else if (TcpUdpState == TCPUDPSudp)
		{
			Serial3.write('U');
		
			if (UdpClientConnectTimeout[0] < TCP_UDP_CLIENT_CONNECT_TIMEOUT)
			{
				UdpClientConnectTimeout[0]++;
				Serial3.write('0');
				UdpServer[0].beginPacket(UdpServer[0].remoteIP(), UdpServer[0].remotePort());
				UdpServer[0].write(str);
				UdpServer[0].write(" 0: ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n");
				UdpServer[0].endPacket();
			}
			
			if (UdpClientConnectTimeout[1] < TCP_UDP_CLIENT_CONNECT_TIMEOUT)
			{
				UdpClientConnectTimeout[1]++;
				Serial3.write('1');
				UdpServer[1].beginPacket(UdpServer[1].remoteIP(), UdpServer[1].remotePort());
				UdpServer[1].write(str);
				UdpServer[1].write(" 1: abcdefghijklmnopqrstuvwxyz\r\n");
				UdpServer[1].endPacket();
			}
			
			if (UdpClientConnectTimeout[2] < TCP_UDP_CLIENT_CONNECT_TIMEOUT)
			{
				UdpClientConnectTimeout[2]++;
				Serial3.write('2');
				UdpServer[2].beginPacket(UdpServer[2].remoteIP(), UdpServer[2].remotePort());
				UdpServer[2].write(str);
				UdpServer[2].write(" 2: !@#$%^&*()_+1234567890-={[}]|:;?/>.<,\r\n");
				UdpServer[2].endPacket();
			}
			
			if (UdpClientConnectTimeout[3] < TCP_UDP_CLIENT_CONNECT_TIMEOUT)
			{
				UdpClientConnectTimeout[3]++;
				Serial3.write('3');
				UdpServer[3].beginPacket(UdpServer[3].remoteIP(), UdpServer[3].remotePort());
				UdpServer[3].write(str);
				UdpServer[3].write(" 3: !@#$%^&*()_+1234567890-={[}]|:;?/>.<,\r\n");
				UdpServer[3].endPacket();
			}
		}
	}

	if (uliTime > uliTime100)
	{
		uliTime100 += 100;
		
		if (TcpUdpState == TCPUDPStcp)
		{
			for (iTcpServer = 0; iTcpServer < SERVER_MAX; iTcpServer++)
			{
	  			while ((TcpClient = TcpServer[iTcpServer].available()) == true)
				{
					b = TcpClient.read();
					
					if (b == 0x06)
					{
						TcpClientConnectTimeout[iTcpServer] = 0;
					}
					
					if ((b > 0x20) && (b < 0x7f))
					{
						sprintf(str, "(%02x,%c)", b, b);
					}
					else
					{
						sprintf(str, "(%02x)", b);
					}
					Serial3.print(str);
				}
			}
		}
		
		else if (TcpUdpState == TCPUDPSudp)
		{
			for (iUdpServer = 0; iUdpServer < SERVER_MAX; iUdpServer++)
			{
				iPacketSize = UdpServer[iUdpServer].parsePacket();
			
				if (iPacketSize)
				{
					UdpServer[iUdpServer].read(cPacketBuffer, UDP_TX_PACKET_MAX_SIZE);
					
					for (i = 0; i < iPacketSize; i++)
					{
						b = cPacketBuffer[i];
						
						if (b == 0x06)
						{
							UdpClientConnectTimeout[iUdpServer] = 0;
						}
						
						if ((b > 0x20) && (b < 0x7f))
						{
							sprintf(str, "(%02x,%c)", b, b);
						}
						else
						{
							sprintf(str, "(%02x)", b);
						}
						Serial3.print(str);
					}
				}
			}
		}
	}
}

Is there a reason you want to switch between 4 tcp sockets and 4 udp sockets? What is the goal of this?

  1. Yes.
  2. To be able to switch.
    The way I am switching works (at least as far as 10 cycles of testing goes). The question is, will it prove to be robust long term? Am I violating any rules? Are there objects, memory, etc. that are left around by making the apparently unexpected BEGIN calls?

So this is just an exercise in programming logic? How would your "clients" know whether the sockets are tcp or udp? That would be the only "rule" your code violates.

Thanks for your replies. Let's just say that my customer wants to offer both tcp and udp, but not at the same time. So, it is safe to rely on Ethernet.begin() to "reset" the WizNet W5100 system so that there are no memory leaks or other history issues, yes?

SJFreeland:
Thanks for your replies. Let's just say that my customer wants to offer both tcp and udp, but not at the same time. So, it is safe to rely on Ethernet.begin() to "reset" the WizNet W5100 system so that there are no memory leaks or other history issues, yes?

Yes.

I have to pound on it, but everything seems to work. THNX again.