TCP Tutorial

From openPicus Wiki
Jump to: navigation, search

Contents

What you are going to learn

This tutorial will show you how to achieve a consistent TCP data exchange using our modules.

TCP and Networking basics

Sending data through the internet is no trivial task: involving multiple stacked layers of communication, intense packet management at every level, multiple possibly unknown in-between machines, it can get complicated fast. Luckily the Flyport APIs hide all this behind a very simple interface.

Here is a code snippet to open a TCP Server socket.

TCP_SOCKET SocketTCPServer = TCPServerOpen("5555");
if (SocketTCPServer != INVALID_SOCKET)
	UARTWrite(1, "Tcp socket opened succesfully\n");

Here is a code snippet to open a TCP Client socket.

TCP_SOCKET SocketTCPClient = TCPClientOpen("www.mydomain.com", "5555");
if (SocketTCPClient != INVALID_SOCKET)
	UARTWrite(1, "Tcp socket opened succesfully\n");

As you can see it's pretty simple.

Setting

Creating a new project, it is advisable to add more space to TX and RX Buffer at the both Generic Sockets in the Wizard.
One HTTP Server Socket must be deleted to take this space.

Tcp socket.jpg


Sending/receiving‎ data to/from a TCP Server with a Flyport as a TCP Client

It is really easy to send some data to a TCP Server.

At a first step a TCP Server must be configured if it doesn't exist. A simple TCP Server can be setted up using some software like TCP/IP Builder.

Builder init.jpg

In this case the server has the following IP 192.168.2.3 and listens on the 5555 TCP port.

A TCP Client example:

#include "taskFlyport.h"
 
void FlyportTask()
{
  TCP_SOCKET sock = INVALID_SOCKET;
  char msg[500];
  int cnt =0;
  BOOL flagErr = FALSE;
 
  // Flyport connects to default network
  WFConnect(WF_DEFAULT);
  while(WFGetStat() != CONNECTED);
  while(!DHCPAssigned);
  vTaskDelay(25);
  UARTWrite(1,"Flyport Wi-fi G connected...hello world!\r\n");
 
  //Creates message to send to the server
  sprintf(msg,"%s","Hello server...");
 
  //Connects the TCP Client to the server
  sock = TCPClientOpen("192.168.2.3","5555");
 
  //Timeout function
  while(!TCPisConn(sock)) 
  {
    if(cnt==10)
    {
      flagErr = TRUE;
      break;
    }
    vTaskDelay(50);
    cnt++;
  }
 
  if(flagErr)
  {
    UARTWrite(1,"\r\nTimeout error...\r\n");		
  }
  else
  {
    int len = TCPWrite(sock, msg, strlen(msg));
 
    sprintf(msg,"\r\nLength data: %d\r\n",len);
    UARTWrite(1,msg);
  }
 
  //With the following code it is possible to receive data
  //from the server and print on the UART the message
  char bff[250];
  int RxLen=0;
  while(1)
  {
    msg[0]='\0';	
    while((RxLen=TCPRxLen(sock))>0)
    {
      TCPRead(sock,bff,RxLen);
      strcat(msg,bff);
    }
    if(msg[0]!='\0')
      UARTWrite(1,msg);
  }
}

The result is this

Builder hello.jpg


Sending/receiving‎ data to/from a TCP Client with a Flyport as a TCP Server

It's very easy to turn a flyport in a TCP Server, you can use this function:

TCP_SOCKET TCPServerOpen(char * PORT)

With this function, the flyport listens on the PORT. When a client connects to it, the flyport can read or write data from/to the client.

A TCP Server example:

#include "taskFlyport.h"
 
void FlyportTask()
{
  TCP_SOCKET sock = INVALID_SOCKET;
  char msg[500];
 
  BOOL flagConn = FALSE;
 
  // Flyport connects to default network
  WFConnect(WF_DEFAULT);
  while(WFGetStat() != CONNECTED);
  while(!DHCPAssigned);
  vTaskDelay(25);
  UARTWrite(1,"Flyport Wi-fi G connected...hello world!\r\n");
 
  sock = TCPServerOpen("8888");
 
  UARTWrite(1,"\r\nTCP Server is ready (PORT: 8888)\r\n");
 
  char bff[250];
  int RxLen=0;
 
  while(1)
  {
    if(TCPisConn(sock))
    {
      if(!flagConn)
      {
        UARTWrite(1,"\r\nClient is connected\r\n");
	sprintf(msg,"Welcome!");
	TCPWrite(sock,msg,strlen(msg));
	flagConn = TRUE;
      }
    }
    else
    {
      if(flagConn)
      {
	UARTWrite(1,"\r\nClient is disconnected\r\n");
	flagConn = FALSE;
      }
    }
 
    if(flagConn == TRUE)
    {
      msg[0]='\0';
      while((RxLen=TCPRxLen(sock))>0)
      {
        TCPRead(sock,bff,RxLen);
	strcat(msg,bff);
      }
      if(strlen(msg)>0)
      {
        sprintf(bff,"\r\nClient message: %s\r\nBytes received:%d\r\n",msg,strlen(msg));
	UARTWrite(1,bff);
	sprintf(msg,"\r\nBytes received:%d\r\n",strlen(msg));
	TCPWrite(sock,msg,strlen(msg));
      }
    }
  }
}


When this firmware starts, you can see the flyport IP in the Serial Monitor in the IDE and you can use it in TCP/IP Builder

Ip server.jpg

Client builder.jpg

When TCP/IP Builder connects to the flyport, it responds with "Welcome!".

If some messages are sent from the client, the flyport reads the buffer (linked to the socket), it writes the data on the Serial Monitor and it sends to the TCP/IP Builder the number of bytes received.
Datareceived.jpg

Senttoserver builder.jpg

How to communicate with a web server

To communicate with a web server, the flyport must connect to the web server and then it must send an HTTP Request.
The message of this request must be built in a specific and correct way or the server will respond with an error message (HTTP 400 Bad Request).

HTTP Methods:
- OPTIONS
- GET
- HEAD
- POST
- PUT
- DELETE
- TRACE
- CONNECT

The most useful request is the messages with GET method.

Every request must be terminated with two couples of CR (Carriage Return \r) and LF (New Line \n). Every line must be terminated with a couple of CR+LF.
Example 1:

GET /index.html HTTP/1.1\r\n
HOST: www.google.com\r\n
\r\n
\r\n

Example 2:

GET /index.html HTTP/1.1\r\n
HOST: www.google.com\r\n\r\n

Last header has two couples of CR+LF.

GET Method

The GET method is used to request an internet page (any type) or to send a very small number of parameters to an internet page.
The GET request minimum structure is the following:

GET [PATH] HTTP/1.1
HOST: [WEBSITE]
[HEADERS]


[WEBSITE] is the internet web site where the page is located.

HOST: www.google.com


[PATH] is the page path with or without parameters.
Without parameters:

GET /index.html HTTP/1.1

With parameters:

GET /index.php?param1=value1&param2=value2 HTTP/1.1

The parameters are preceded by a question mark (?) and between any couple of parameter=value there is an ampersand (&).

[HEADERS] is the space where it is possibile to add more headers like FROM, ACCEPT and etc.

A GET Request firmware example:

#include "taskFlyport.h"
 
void FlyportTask()
{
  TCP_SOCKET sock = INVALID_SOCKET;
  char msg[1500];
  int cnt =0;
  BOOL flagErr = FALSE;
 
  //Flyport connects to default network
  WFConnect(WF_DEFAULT);
  while(WFGetStat() != CONNECTED);
  while(!DHCPAssigned);
  vTaskDelay(25);
  UARTWrite(1,"Flyport Wi-fi G connected...hello world!\r\n");
 
  sock = TCPClientOpen("www.openpicus.com","80");
 
  while(!TCPisConn(sock))
  {
    if(cnt==10)
    {
      flagErr = TRUE;
      break;
    }
    vTaskDelay(50);
    cnt++;
  }
 
  if(flagErr)
  {
    UARTWrite(1,"\r\nTimeout error...\r\n");
    sock=INVALID_SOCKET;
  }
 
  UARTWrite(1,"\r\nFlyport is ready to make a GET request\r\n");
 
  char bff[250];
  int RxLen=0;
  int LenTOT=0;
  while(1)
  {		
    if(TCPisConn(sock))
    {
      //this function puts in msg (char array) the GET request
      sprintf(msg,"GET /index.php HTTP/1.1\r\nHOST: www.openpicus.com\r\n\r\n");
      UARTWrite(1,"\r\nRequest:\r\n");
      UARTWrite(1,msg);
      TCPWrite(sock,msg,strlen(msg));
      vTaskDelay(100);
      msg[0]='\0';
      while((RxLen=TCPRxLen(sock))>0&&LenTOT<(1500-250))
      {
        if(RxLen>240)
	{
	  TCPRead(sock,bff,240);
          LenTOT=LenTOT+240;
	}
	else
	{
	  TCPRead(sock,bff,RxLen);
	  LenTOT=LenTOT+RxLen;
	}
	strcat(msg,bff);
      }
      if(strlen(msg)>0)
      {
	UARTWrite(1,"\r\nResponse:\r\n");
	UARTWrite(1,msg);
	TCPClientClose(sock);
        vTaskDelay(100);
      }
    }
  }
}

Serial Monitor debug with response:

Flyport Wi-fi G connected...hello world!
 
Flyport is ready to make a GET request
 
Request:
GET /index.php HTTP/1.1
HOST: www.openpicus.com
 
 
Response:
HTTP/1.1 200 OK
Date: Tue, 31 Dec 2013 14:45:33 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
X-Drupal-Cache: HIT
Etag: "1388499215-0"
Content-Language: en
X-Generator: Drupal 7 (http://drupal.org)
Cache-Control: public, max-age=86400
Last-Modified: Tue, 31 Dec 2013 14:13:35 +0000
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Vary: Cookie,Accept-Encoding
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
 
4192
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
  "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" version="XHTML+RDFa 1.0" dir="ltr"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:dc="http://purl.org/dc/terms/"
  xmlns:foaf="http://xmlns.com/foaf/0.1/"
  xmlns:og="http://ogp.me/ns#"
  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
  xmlns:sioc="http://rdfs.org/sioc/ns#"
  xmlns:sioct="http://rdfs.org/sioc/types#"
  xmlns:skos="http://www.w3.org/2004/02/skos/core#"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
 
<head profile="http://www.w3.org/1999/xhtml/vocab">
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
...
[incomplete response - too big]

In this case the openpicus web page is not suitable to download by the embedded system. The normal pages are too big for the IoT systems.

Personal tools
Namespaces

Variants
Actions
START HERE
DEVELOPMENT
HARDWARE INFO
RESOURCES
PHASED OUT
Toolbox