CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

HTTP GET using TCP Client

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ajt



Joined: 07 Sep 2003
Posts: 110

View user's profile Send private message

HTTP GET using TCP Client
PostPosted: Fri Jul 13, 2012 11:05 am     Reply with quote

Using the CCS stack and demo board, I can run example 13 with TCPserver.exe running on a PC and everything works as it should. (compiler/IDE version 4.134)

I have placed a small PHP script at testani.net (72.34.42.193) that returns the server's UTC time, i.e.
http://testani.net/timestamp.php
which, as you can see, works from a browser. It also works from a small Delphi program I wrote to test it using a HTTP client component.

I am stuck trying to make this work using the CCS stack. I modified example 13 as follows and cannot get a response from the server although it does seem to connect. The essential changes to ex13.c are to change the port to 80 (for HTTP) and the TCPPutArray string to "GET /timestamp.php HTTP/1.1\r\n". I have checked router and server logs and do not see any of the activity from this test but do see it for the browser case.

I've searched the CCS forum as well as have done searches on sending HTTP requests using a TCP client and related topics and cannot figure out what I am going wrong. Any help would be appreciated!

Modified ex13.c follows. You can see I added some LCD output and also some infinite loops to keep any reconnection from happening. I did it this way to not mess with the state machine at all.
Code:
//////////////////////////////////////////////////////////////////////////////
//
// **MODIFIED** ex13.c
//
// A TCP example, where the PIC acts as a TCP client. 
//
// NOTE: You MUST change the code in ServerAddrInit() to specify the IP address
//       of the PC running TCPSERVER.EXE
//
// NOTE: Change the code in IPAddrInit() to your desired IP address, which
//       is based on your network.
//
//////////////////////////////////////////////////////////////////////////////

#define STACK_USE_ICMP  1
#define STACK_USE_ARP   1
#define STACK_USE_TCP   1
#include "ccstcpip.h"

IP_ADDR server;

#define EXAMPLE_TCP_PORT   (int16)80

//this function is called by MyTCPTask() when the specified socket is connected
//returns TRUE if BUTTON2 was pressed, therefore we must disconnect the socket
int8 TCPConnectedTask(TCP_SOCKET socket) {
   char c;
   static int8 counter;
   char str[32];
   static int8 button1_held;
   int16 num_sent;

   if (TCPIsGetReady(socket)) {
      printf(lcd_putc,"\f");
      while (TCPGet(socket, &c)) {
         lcd_putc(c);
      }
      printf(lcd_putc, "\nSOCKET ACTIVE");
   }

//when button 1 is pressed: send message over TCP
//when button 2 is pressed: disconnect socket
   if (BUTTON1_PRESSED() && !button1_held && TCPIsPutReady(socket)) {
      button1_held=TRUE;
//      sprintf(str,"BUTTON C=%U",counter++);
      strcpy(str,"GET /timestamp.php HTTP/1.1\r\n");
      if (TCPIsConnected(socket)){
      num_sent = 0;
      num_sent = TCPPutArray(socket,str,strlen(str));
      TCPFlush(socket);
      }
      lcd_putc("\f");
      printf(lcd_putc, "num_sent: %Lu", num_sent);
      lcd_putc("\n");
      printf(lcd_putc, str);
      }
   if (!BUTTON1_PRESSED()) {
      button1_held=FALSE;
   }
  #if defined(BUTTON2_PRESSED())
   if (BUTTON2_PRESSED()) {
      return(TRUE);
   }
  #endif
   return(FALSE);
}

void MyTCPTask() {
   static TICKTYPE lastTick;
   static TCP_SOCKET socket=INVALID_SOCKET;
   static enum {
      MYTCP_STATE_NEW=0, MYTCP_STATE_ARP_REQ=1, MYTCP_STATE_ARP_WAIT=2,
      MYTCP_STATE_CONNECT=3, MYTCP_STATE_CONNECT_WAIT=4,
      MYTCP_STATE_CONNECTED=5, MYTCP_STATE_DISCONNECT=6,
      MYTCP_STATE_FORCE_DISCONNECT=7
   } state=0;
   static NODE_INFO remote;
   TICKTYPE currTick;
   int8 dis;

   currTick=TickGet();

   switch (state) {
      case MYTCP_STATE_NEW:
         memcpy(&remote.IPAddr, &server, sizeof(IP_ADDR));
         printf(lcd_putc,"\fARP REQUEST TO\n");
         lcd_display_ip(&server);
         state=MYTCP_STATE_ARP_REQ;

      case MYTCP_STATE_ARP_REQ:
         if (ARPIsTxReady()) {
            ARPResolve(&remote.IPAddr);
            lastTick=currTick;
            state=MYTCP_STATE_ARP_WAIT;
         }
         break;

      case MYTCP_STATE_ARP_WAIT:
         if (ARPIsResolved(&remote.IPAddr, &remote.MACAddr)) {
            state=MYTCP_STATE_CONNECT;
         }
         else if (TickGetDiff(currTick, lastTick) > (TICKS_PER_SECOND * 2)) {
            state=MYTCP_STATE_ARP_REQ;
         }
         break;

      case MYTCP_STATE_CONNECT:
         printf(lcd_putc,"\fCONNECTING TO\n");
         lcd_display_ip(&server);
         socket=TCPConnect(&remote, EXAMPLE_TCP_PORT);
         if (socket!=INVALID_SOCKET) {
            lastTick=TickGet();
            state=MYTCP_STATE_CONNECT_WAIT;
         }
         else {
            printf(lcd_putc,"\fSOCKET ERROR");
         }
         break;

      case MYTCP_STATE_CONNECT_WAIT:
         if (TCPIsConnected(socket)) {
            state=MYTCP_STATE_CONNECTED;
            printf(lcd_putc,"\fCONNECTED TO\n");
            lcd_display_ip(&server);
         }
         else if (TickGetDiff(currTick, lastTick) > (TICKS_PER_SECOND * 10)) {
            state=MYTCP_STATE_FORCE_DISCONNECT;
         }
         break;

      case MYTCP_STATE_CONNECTED:
         if (TCPIsConnected(socket)) {
            dis=TCPConnectedTask(socket);
            if (dis) {
               state=MYTCP_STATE_DISCONNECT;
               lastTick=currTick;
            }
         }
         else {
            printf(lcd_putc,"\fDISCONNECTED");
            state=MYTCP_STATE_CONNECT;
            printf(lcd_putc, "\fSTOPPED in loop");
            while(1);  //!!!!!!!!!!!!!!!
         }
         break;

      case MYTCP_STATE_DISCONNECT:
         printf(lcd_putc,"\fDISCONNECT FROM\n");
         lcd_display_ip(&server);
         if (TCPIsPutReady(socket)) {
            state=MYTCP_STATE_FORCE_DISCONNECT;
         }
         else if (TickGetDiff(currTick, lastTick) > (TICKS_PER_SECOND * 10)) {
            state=MYTCP_STATE_FORCE_DISCONNECT;
         }
         break;

      case MYTCP_STATE_FORCE_DISCONNECT:
         TCPDisconnect(socket);
         state=MYTCP_STATE_CONNECT;
         printf(lcd_putc, "\fSTOPPED in loop");
         while(1); //!!!!!!!!!!!!!!!
         break;
   }
}

void ServerAddrInit(void) {
   //IP address of  testani.net
   server.v[0]=72;
   server.v[1]=34;
   server.v[2]=42;
   server.v[3]=193;
//   server.v[0]=192;
//   server.v[1]=168;
//   server.v[2]=167;
//   server.v[3]=34;
   
}

void main(void)
{
   printf("\r\n\nCCS TCP/IP TUTORIAL, EXAMPLE 13 (TCP CLIENT)\r\n");
   
   Init();
   ServerAddrInit();
   lcd_init();
   
   printf(lcd_putc,"\fCCS TCP TUTORIAL\nINIT");
   
   StackInit();
   
   while(TRUE) {
      StackTask();
      MyTCPTask();
   }
}
[/code]
_________________
Al Testani
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Jul 13, 2012 11:57 am     Reply with quote

There's two things I can think of:

1. You need a blank line after the request:
Code:
strcpy(str,"GET /timestamp.php HTTP/1.1\r\n\r\n");


2. HTTP/1.1 requires a Host header (HTTP/1.0 does not):
Code:
strcpy(str,"GET /timestamp.php HTTP/1.1\r\nHost: testani.net\r\n\r\n");


BTW, all HTTP servers should include the current time in their response headers, so you shouldn't need a special script to return the time, and in that case you could also use a HEAD request instead of a GET.
_________________
Andrew
dpechman



Joined: 04 Dec 2007
Posts: 43

View user's profile Send private message Visit poster's website

PostPosted: Fri Jul 13, 2012 12:06 pm     Reply with quote

Hi,

I did it work sometime ago using the same sample and include dns client.

First look seems you forget to include "<CR><LF>" at the end of get sentence HTTP/1.1<CR><LF>

Code:

IP_ADDR server;
char SERVER_NAME[64]="servername.com";

#define MY_TCP_PORT   (int16)80

int8 TCPConnectedTask(TCP_SOCKET socket) {
   char c;
   static int8 counter;
   char str[20];
   static int8 button1_held;

   if (TCPIsGetReady(socket)) {
      while (TCPGet(socket, &c)) {
         Lcd_Putc(c);
      }
   }

   if (trigger==1 && TCPIsPutReady(socket)) {
      disparar=0;
      sprintf(str,"GET /services/srv.php?operation=doLogin HTTP/1.1<CR><LF>"); 

      TCPPutArray(socket,str,strlen(str));
      TCPFlush(socket);
   }
 
   return(FALSE);
}

void MyTCPTask() {
   static TICKTYPE lastTick;
   static TCP_SOCKET socket=INVALID_SOCKET;
   static enum {
      MYTCP_STATE_DNSSET=0, MYTCP_STATE_GET_DNS=1,
      MYTCP_STATE_NEW=2, MYTCP_STATE_ARP_REQ=3, MYTCP_STATE_ARP_WAIT=4,
      MYTCP_STATE_CONNECT=5, MYTCP_STATE_CONNECT_WAIT=6,
      MYTCP_STATE_CONNECTED=7, MYTCP_STATE_DISCONNECT=8,
      MYTCP_STATE_FORCE_DISCONNECT=9
   } state=0;   
   static NODE_INFO remote;
   TICKTYPE currTick;
   int8 dis;

   currTick=TickGet();

   switch (state) {
   
      case MYTCP_STATE_DNSSET:
         DNSResolve(SERVER_NAME);
         lastTick = currTick;
         state = MYTCP_STATE_GET_DNS;
      break;
         
      case MYTCP_STATE_GET_DNS:
         if (DNSIsResolved(&server))
         {
            state = MYTCP_STATE_NEW;
         }
         else if (TickGetDiff(currTick, lastTick) > (TICKS_PER_SECOND * 30))
         {
            state = MYTCP_STATE_DNSSET;
         }
      break;   
   
      case MYTCP_STATE_NEW:
         memcpy(&remote.IPAddr, &server, sizeof(IP_ADDR));
         Lcd_Gotoxy(1,1);
         Lcd_Putc("\nARP REQUEST     ");
         state=MYTCP_STATE_ARP_REQ;
      break;

      case MYTCP_STATE_ARP_REQ:
         if (ARPIsTxReady()) {
            ARPResolve(&remote.IPAddr);
            lastTick=currTick;
            state=MYTCP_STATE_ARP_WAIT;
         }
      break;

      case MYTCP_STATE_ARP_WAIT:
         if (ARPIsResolved(&remote.IPAddr, &remote.MACAddr)) {
            state=MYTCP_STATE_CONNECT;
            //Lcd_Gotoxy(2,1);
            //Lcd_Putc("\nCONNECTING      ");
           
            Lcd_Gotoxy(2,1);
            printf(Lcd_Caracter, "%u.%u.%u.%u", MY_IP_BYTE1, MY_IP_BYTE2, MY_IP_BYTE3, MY_IP_BYTE4);

         }
         else if (TickGetDiff(currTick, lastTick) > (TICKS_PER_SECOND * 2)) {
            state=MYTCP_STATE_ARP_REQ;
         }
      break;

      case MYTCP_STATE_CONNECT:
         socket=TCPConnect(&remote, MY_TCP_PORT);
         if (socket!=INVALID_SOCKET) {
            lastTick=TickGet();
            state=MYTCP_STATE_CONNECT_WAIT;
         }
         else {
            //Lcd_Gotoxy(2,1);
            //Lcd_Putc("\nSOCKET ERROR    ");
         }
      break;

      case MYTCP_STATE_CONNECT_WAIT:
         if (TCPIsConnected(socket)) {
            state=MYTCP_STATE_CONNECTED;
            leds=16;
            Lcd_Gotoxy(2,1);
            Lcd_Putc("\nCONNECTED!      ");           
         }
         else if (TickGetDiff(currTick, lastTick) > (TICKS_PER_SECOND * 10)) {
            state=MYTCP_STATE_FORCE_DISCONNECT;
         }
      break;

      case MYTCP_STATE_CONNECTED:
         if (TCPIsConnected(socket)) {
            dis=TCPConnectedTask(socket);
            if (dis) {
               state=MYTCP_STATE_DISCONNECT;
               lastTick=currTick;
            }
         }
         else {
            Lcd_Gotoxy(2,1);
            Lcd_Putc("\nDISCONNECTED    ");
           
            state=MYTCP_STATE_CONNECT;
         }
      break;

      case MYTCP_STATE_DISCONNECT:
         Lcd_Gotoxy(2,1);
         Lcd_Putc("\nDISCONNECTING   ");
         if (TCPIsPutReady(socket)) {
            state=MYTCP_STATE_FORCE_DISCONNECT;
         }
         else if (TickGetDiff(currTick, lastTick) > (TICKS_PER_SECOND * 10)) {
            state=MYTCP_STATE_FORCE_DISCONNECT;
         }
      break;

      case MYTCP_STATE_FORCE_DISCONNECT:
         TCPDisconnect(socket);
         state=MYTCP_STATE_CONNECT;
      break;
   }
}
ajt



Joined: 07 Sep 2003
Posts: 110

View user's profile Send private message

PostPosted: Fri Jul 13, 2012 4:24 pm     Reply with quote

andrewg wrote:


2. HTTP/1.1 requires a Host header (HTTP/1.0 does not):
Code:
strcpy(str,"GET /timestamp.php HTTP/1.1\r\nHost: testani.net\r\n\r\n");


BTW, all HTTP servers should include the current time in their response headers, so you shouldn't need a special script to return the time, and in that case you could also use a HEAD request instead of a GET.


Thanks! This was it and I now have it working. The reason I am using the PHP script is the returned UTC string is in the exact format I need it in. I could have done all of the conversion in PIC code but this was much easier. I still have to parse the header for the date and I just have to go further to get at the PHP return. I am using the required number of TCPGet calls until I get to the string of interest.
_________________
Al Testani
ajt



Joined: 07 Sep 2003
Posts: 110

View user's profile Send private message

PostPosted: Fri Jul 13, 2012 4:26 pm     Reply with quote

dpechman wrote:
Hi,

I did it work sometime ago using the same sample and include dns client.

First look seems you forget to include "<CR><LF>" at the end of get sentence HTTP/1.1<CR><LF>



This is very useful code to me as I need to add the DNS section as well. Thanks!
_________________
Al Testani
dpechman



Joined: 04 Dec 2007
Posts: 43

View user's profile Send private message Visit poster's website

PostPosted: Fri Jul 13, 2012 5:00 pm     Reply with quote

yeah, this is a pretty good way to keep pic connected to internet. I am also using this approach in my last designs.

In the php side you can do a long polling to keep connection always up with minimum bandwidth.

If you want, we can exchange some ideas about it.

Now my system is using http client, dns client, get and set passing data from pic to php webservices and the other way around.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group