USOCKET fnTCP_Connect(
USOCKET TCP_socket,
unsigned char * RemoteIP,
unsigned short usRemotePort,
unsigned short usOurPort,
unsigned short usMaxWindow);
TCP_socket is the number of the TCP socket that should be connected on
RemoteIP is the IP address of the destination that should be connected to
usRemotePort is the remote TCP port number that is to be connected to
usOurPort is the source TCP port number that is to be used for the connection
usMaxWindow is maximum TCP receive buffer size used by the connection. If set to zero the default value
TCP_MAX_WINDOW_SIZE
(the maximum Ethernet buffer size) is used
The routine returns the number of the socket if the connection attempt could be successfully started. Possible errors are:
- SOCKET_NOT_FOUND - invalid socket used
- NO_FREE_PORTS_AVAILABLE - if usOurPort with value 0 is passed the function defines a port number for use. If no
free port number could be defined an error will be returned (this error is never extected to occur)
- SOCKET_STATE_INVALID - the socket is not in a state which allows a connection attempt, for example it may already be connected
Note that, if the project define
REUSE_TIME_WAIT_SOCKETS is active a socket in the states
TCP_STATE_TIME_WAIT or
TCP_STATE_FIN_WAIT_2 will
be allowed to start a new connection. This allows a connection to be made on a socket which is presently waiting for the 2MSL timeout or blocked
in the
TCP_STATE_FIN_WAIT_2 state (due to disconnected TCP parter). See the TCP state transition diagram as reference:
µTasker TCP State Transition Diagram
The TCP connection attempt starts by sending a TCP SYN to the defined port numnber at the destination IP address. The SYN can optionally advertise the maximum segment size (MSS)
of the TCP connection - this is the case when the project define
ANNOUNCE_MAX_SEGMENT_SIZE is enabled.
If the destination address first needs to be resolved on the Ethernet the SYN can not yet be transmitted. Instead first an ARP resolve transmission is initiated instead.
Which of the cases that actually takes place is not reported since it is of no real importance to the calling function. If the ARP resolution is required this will first
complete and the TCP task will then complete the SYN transmission - this doesn't involve any further interaction with the caller.
For the TCP connection be complete the TCP partner must answer with a SYN + ACK and then the socket confirms by sending an ACK. This takes place automatically in the TCP module,
including retransmissions in case of message loss. Once the TCP connection has successfully taken place the TCP event
TCP_EVENT_CONNECTED is received by the
socket's call back function. Once the connection has been established data transfer can commence.
The connection attempt may not always be successful. The following TCP events are used to report failures as follows:
- TCP_EVENT_ABORT - the remote server refused the attempted connection or the connection attempt terminated after maximum attempts
- TCP_EVENT_ARP_RESOLUTION_FAILED - the connection attempt couldn't be made since the remote IP address, or the local gateway, could not be resolved in the network
Example
The first example shows a typical TCP client connection using a fixed destination IP address.
The source port number is not specified so the TCP connection routine choses a suitable port value.
No specific receive window size is given when connection, so the stanard value equal to the maximum Ethernet reception frame length is used.
static int fnPOP3Listener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen);
static USOCKET POP_TCP_socket = -1;
static unsigned char ipPOP3[IPV4_LENGTH] = {192, 168, 0, 100};
....
if (POP_TCP_socket < 0) { // we have no socket - or called before initialisation complete
if ((POP_TCP_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnPOP3Listener)) < 0) {
return ERROR_POP3_NOT_READY;
}
}
if (fnTCP_Connect(POP_TCP_socket, ipPOP3, POP_PORT, 0, 0) == POP_TCP_socket) {
fnDebugMsg("Connecting to mail server\r\n");
}
....
// Local listener on POP3 port
//
static int fnPOP3Listener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen)
{
if (Socket != POP_TCP_socket) {
return APP_REJECT; // ignore if not our socket
}
switch (ucEvent) {
case TCP_EVENT_CONNECTED:
fnDebugMsg("POP3 TCP connection established!!!\r\n");
break;
case TCP_EVENT_CONREQ: // we do not accept connection requests
default:
return APP_REJECT;
}
return APP_ACCEPT;
}
The second example shows a case where the source and destination port numbers are defined to be the same and the size of the TCP reception buffer is being announced according to buffer space which is being reserved especially
for this use. By using the function
fnReportWindow(); the receiver window size is then updated to respect the remaining space in the buffer and thus realise TCP flow control.
Note that the project define
CONTROL_WINDOW_SIZE is needed to work with
fnReportWindow();.
static int fnListener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen);
static USOCKET POP_TCP_socket = -1;
static unsigned char ipAddress[IPV4_LENGTH] = {192, 168, 0, 100};
static unsigned char ucBuffer[8 * 1024];
static int iBufferPosition = 0;
....
if (fnTCP_Connect(Test_TCP_socket, ipAddress, 1234, 1234, sizeof(ucBuffer)) == POP_TCP_socket) {
fnDebugMsg("Connecting to server\r\n");
}
....
// Local listener
//
static int fnListener(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen)
{
if (Socket != POP_TCP_socket) {
return APP_REJECT; // ignore if not our socket
}
switch (ucEvent) {
case TCP_EVENT_CONNECTED:
fnDebugMsg("TCP connection established!!!\r\n");
break;
case TCP_EVENT_DATA:
uMemcpy(&ucBuffer[iBufferPosition], ucIp_Data, usPortLen); // save the received packet to the buffer
iBufferPosition += usPortLen;
fnReportWindow(Socket, (sizeof(ucBuffer) - iBufferPosition)); // update the receive buffer size remaining to quench TCP reception when necessary
break;
case TCP_EVENT_CONREQ: // we do not accept connection requests
default:
return APP_REJECT;
}
return APP_ACCEPT;
}
See the following forum thread for additional details about working with TCP sockets:
µTasker forum TCP discussion.
Related functions
fnGetTCP_Socket();
fnReleaseTCP_Socket();
fnTCP_Listen();
fnGetTCP_state();
fnReportWindow();
fnTCP_Activity();
fnTCP_close();
Please use the
µTasker forum to ask specific questions.