fnTCP_Connect()

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: 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:

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.