EthernetTCPServer

This code will serve up to eight simultaneous TCP clients. The client program located on your PC sends a text message to the PIC host, which then sends a confirmation message back to the client application. The sample program uses DHCP and also allows you to ping the Ethernet device.

An interesting feature is the use of the NBNS module. When using DHCP, the IP address of the unit may change each time it is connected to the network. So how do we connect if the IP address may change each time the unit is connected? The NBNS module allows you to assign a host name to the device. In the example shown, the TCP client does not have to know the IP address of the device. Instead, you can connect using "swordfish", as shown in the image to the right. As mentioned earlier, the code will support up to eight simultaneous clients. This means you can start eight unique instances of the client application on your PC. Each one can communicate with the PIC using an independent socket. If the IP address is known or fixed (that is, you are not using DHCP) then you can enter the IP address into the "Hostname or IP Address" field, rather than using the default NetBIOS name of "swordfish". You can download a simple client program to test the code from here:

Download TCP Client Application »

Here is what you need to do to test the program

  • Plug a network cable into your board and connect to your network. For example, just plug your Ethernet board into your broadband router, which will act as a DHCP server.
  • Compile and then program the code into your device.
  • Start the Swordfish Serial Communicator plugin, and a connect to your MCUs USART at 115200 baud.
  • Reset the MCU.

If all goes well, something like the following should be displayed in the Serial Communicator window

 Waiting for DHCP...
 Host Name     : SWORDFISH      
 MAC Address   : $00 $04 $A3 $00 $00 $00 
 IP address    : 192.123.223.1
 Mask          : 255.255.255.0
 Gateway       : 192.123.223.254

You should now be able to execute and connect up to eight instances of "TCPClient.exe".

Sample Code

// device and clock - code will work on an 18F452 as well...
Device = 18F4680
Clock = 20

// important configurations...
#option ENC28J60_CS = PORTD.6
#option NET_ICMP = true   // enable ping 
#option NET_DHCP = true   // enable Dynamic Host Configuration Protocol (DHCP)
#option NET_NBNS = true   // enable NETBIOS
#option NET_TCP = true    // enable TCP
Include "NETApp.bas"      // always first!

// TCPIP stack specifics...
Include "NETTypes.bas"
Include "NETUtils.bas"
Include "Tick.bas"
Include "TCP.bas"

// program helpers...
Include "NETAppDisplay.bas"
Include "usart.bas"
Include "convert.bas"

// maximum number of TCP server sockets
Const MaxSockets = MAX_TCP_SOCKETS // found in NETConfig, default is eight 

// state machine constants...
Const
   SM_HOME = 0,
   SM_LISTENING = 1   

// structure that holds socket state, connected flag and 
// TCP socket ID...   
Structure TSocket
   State As Byte
   Connected As Boolean
   ID As TCP_SOCKET
   dummy As Byte // 4 byte align
End Structure

// TCP server socket array...
Dim Sock(MaxSockets) As TSocket
{
****************************************************************************
* Name    : TCPServerInit                                                  *
* Purpose : Prepare socket array                                           *
****************************************************************************
}
Sub TCPServerInit()
   Dim Index As Byte
   Dim Socket As TSocket
   For Index = 0 To MaxSockets - 1
      Socket.ID = INVALID_SOCKET 
      Socket.Connected = false
      Socket.State = SM_HOME
      Sock(index) = Socket
   Next
End Sub  
{
****************************************************************************
* Name    : TCPServerOpen                                                  *
* Purpose : Open for listening 'MaxSockets' TCP sockets                    *
****************************************************************************
}
Sub TCPServerOpen()
   Const SERVER_PORT = 9760
   Dim Index As Byte
   Dim Socket As TSocket
   For Index = 0 To MaxSockets - 1
      Socket = Sock(index)
      If Socket.ID = INVALID_SOCKET Then
         Socket.ID = TCPListen(SERVER_PORT)
         If Socket.ID <> INVALID_SOCKET Then
            Socket.State = SM_LISTENING
         EndIf
      EndIf
      Sock(index) = Socket
   Next
End Sub      
{
****************************************************************************
* Name    : TCPServerTask                                                  *
* Purpose : Process the TCP server sockets                                 *
****************************************************************************
}     
Sub TCPServerTask()
   Dim c As Byte
   Dim Index As Byte
   Dim Socket As TSocket

   For Index = 0 To MaxSockets - 1 
      Socket = Sock(index)

      // server socket allocated...
      If Socket.State = SM_LISTENING Then

         // see if a client has disconnected...
	 If Not TCPIsConnected(Socket.ID) Then
	    If Socket.Connected Then
	       Socket.Connected = false
               Write("Client ", DecToStr(Socket.ID), " disconnected",13,10)
            EndIf
	    Sock(index) = Socket
            Continue
         EndIf

         // see if a client has just connected...
         If Not Socket.Connected Then
            Socket.Connected = true
            Write("Client connected, ")
            TCPGetRemoteInfo(Socket.ID)
            Write("IP address is ")
            DisplayIPAddress(TCP.RemoteInfo.Remote.IPAddr)
         EndIf

	 // receive and display any bytes sent...
	 If TCPIsGetReady(Socket.ID) <> 0 Then
	    While TCPGet(Socket.ID, c)
	       Write(c)
	    Wend
            Write(13,10)

	    // transmit  a reply...
	    If TCPIsPutReady(Socket.ID) <> 0 Then
	       TCPPutString(Socket.ID,"Message from server : " + DecToStr(TickGet))
	    EndIf   
         EndIf
      EndIf 
      Sock(index) = Socket
   Next     
End Sub

// program start...
SetBaudrate(br115200)
TCPServerInit()

#if NET_DHCP
Write("Waiting for DHCP...",13,10)
#else
TCPServerOpen()
#endif

// loop forever...
While true

   // This task performs normal stack task including checking for incoming 
   // packet, type of packet and calling appropriate stack entity to process it.
   NETApp.Task
   TCPServerTask() 

   // If DHCP is enabled, display configuration when a DHCP event
   // has occurred - also open our TCP server sockets for listening...
   #if NET_DHCP
   If NETApp.DHCPEvent() Then
      DisplayConfig()
      TCPServerOpen()
   EndIf
   #endif
Wend