Need help troubleshooting TCP code w/ Raspberry Pi

I am having trouble with my Raspberry Pi sending things to the Spark Core. I thought it could’ve been an issue that another member was seeing, but it’s just an issue in my code. I will post the spark core code here:

EDIT: pastebin links are 3-4 posts below


    #define NUM_TRIES 2
    #define MAXLINE 1024
    TCPClient client;
    byte server[] = { 10,0,0,18 }; // Rpi server
    int port = 17060;
    
    char *connect_and_send(char* message);
    void *get_response(char *response);
    char *response_buf = (char*)malloc(sizeof(char) * MAXLINE/4);;
    
    void setup()
    {
        pinMode(D7, OUTPUT);
        Spark.variable("response", response_buf, STRING);
    }
    
    void loop()
    {
        char *response = connect_and_send("GET pi.txt");
        if(response == NULL)
        {
            return;
        }
        strcpy(response_buf, response);
        digitalWrite(D7, HIGH);
        delay(5000);
        if(response != NULL)
            free(response);
        digitalWrite(D7, LOW);
    }
    
    
    //Call this function to connect and send a message. Returns the message it received
    //TODO: make it return an array and make verbose mode where it will echo the response
    inline char *connect_and_send(char *message)
    {
        bool connected = false;
        char *response = (char*)malloc(sizeof(char) * MAXLINE/4);
        if(response == NULL)
            return response;
            
        
        // Tries to connect to server multiple times
        for(int i = 0; i < NUM_TRIES; i++)
        {
            if(client.connect(server,port)) //if connected, send message
            {
                connected = true;
                client.println(message);
                break;
            }
        }
        
        if(connected)   //if connection succeeded, get the file
        {
            get_response(response);
        }
    
        delay(100);
        client.flush();
        client.stop();
        return response;
    }
    
    //Gets the file response from the Raspberry Pi and modifies pointer response
    void *get_response(char *response)
    {
        int count = 0;
        if (client.connected()) 
        {
            // echo all available bytes back to the client
            while (client.available())
            {
                char c = client.read();
                response[count] = c;
                count += 1;
            }
        }
        else 
        {
            digitalWrite(D7, HIGH);
            delay(500);
            digitalWrite(D7, LOW);
        }
    }


    /* 
     * 
     * This is the implementation of my Raspberry Pi TCP Server.
     * 
     * The RPi will connect to the Spark Core through a TCP connection
     * on the port specified on the command line, and will wait for incoming
     * connections on that port. 
     *
     * When a connection is made, the request will be split into two parts,
     * where the request follows the format "method option". Different
     * methods will have different results but the behavior of the 
     * current supported methods are listed below:
     *
     * GET option
     * - The GET method will request a file, where option is the file to be
     *   requested. The file will then be opened and sent to the core.
     *
     *`
     */
    
    #include <stdio.h>
    #include "csapp.h"
    #include <stdbool.h>
    #include <time.h>
    
    //Permission and flags for opening the log file
    #define PERMISSION (S_IROTH | S_IWOTH | S_IXOTH)
    #define FLAGS (O_RDWR | O_CREAT | O_APPEND)
    
    //Assert to print log entries to standard output
    #define PRINT_LOG_ENTRY 1
    
    //Log file and file descriptor
    static const char *log_file = "log.txt";
    int log_fd;
    
    //boolean to help make logs easier to read
    bool put_time = true;
    
    /* Function prototypes */
    void handle_request(int core_fd, char *method, char *option);
    inline void make_log_entry(char *message);
    
    
    int main(int argc, char **argv)
    {
        int listenfd;  /* listening file descriptor */
        int port;      /* port to listen to connections */
        struct sockaddr_in clientaddr;
        unsigned clientlen;
        
        int fd;
        rio_t rio_client;
        
        char buf[MAXLINE];
        char method[100];
        char option[100];
    
        // Ignore SIGPIPE
        Signal(SIGPIPE, SIG_IGN);
    
        if(argc != 2)
        {
            printf("User error. Please enter in ./server <port> \n");
            exit(1);
        }
    
        /* Get port number */
        port = atoi(argv[1]);
    
        /*  Open the log file and make a log entry stating the port*/
        log_fd = Open(log_file, FLAGS, PERMISSION);
        char temp[MAXLINE];
        sprintf(temp, "Opening connection on port: %d", port);
        make_log_entry(temp);
    
        /* Open listening socket on server side */
        listenfd = Open_listenfd(port);
        
        while(1)
        {
            clientlen = sizeof(clientaddr);
            fd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
    
            //Read and parse the request line
            Rio_readinitb(&rio_client, fd);
            Rio_readlineb(&rio_client, buf, MAXLINE);
            
            sscanf(buf, "%s %s", method, option);
            
            handle_request(fd, method, option);
    
            Close(fd);
            put_time = true;
            
        }
    
        return 0;
    }
    
    /* Handles requests from the Spark Core.
     * Current supported methods:
     * GET:
     * - When GET is called, we open the file specified by option
     *   and send it to the Spark Core.
     *
     * METHOD2:
     * - Put more information about METHOD2.
     *
     */
    void handle_request(int core_fd, char *method, char *option)
    {
        int file_fd;       
        rio_t rio;   
        char buf[MAXLINE]; //buffer for contents of file to be written to
        char temp[MAXLINE];
        int n; 
        
        sprintf(temp, "Method:%s\nOption:%s", method, option);
        make_log_entry(temp);
        put_time = false;
    
        if(strcmp(method, "GET") == 0)
        {
            sprintf(temp, "Opening file: %s", option);
            make_log_entry(temp);
    
            //Open file
            file_fd = Open(option, O_RDONLY, 0);
            make_log_entry("Succuess opening file. Starting to send");
            
            Rio_readinitb(&rio, file_fd);
    
            //Send file to Spark Core
            while((n = Rio_readnb(&rio, buf, MAXLINE)) > 2)
            {
                make_log_entry(buf);
                Rio_writen(core_fd, buf, n);
            }
            
            make_log_entry("Done sending file\n");
            Close(file_fd);
        }
        return;
    }
    
    /* Makes a log entry with message to the log file declared at the top
     * of this file. Only displays the time on the log if its a new request.
     */
    inline void make_log_entry(char *message)
    {
        if(put_time)
        {
            time_t curr_time;
            char *curr_time_str;
            curr_time = time(NULL);
            curr_time_str = ctime(&curr_time);
            write(log_fd, curr_time_str, strlen(curr_time_str));
        }
        
        if(PRINT_LOG_ENTRY) printf("%s\n", message);
        
        write(log_fd, message, strlen(message));
        write(log_fd, "\n", strlen("\n")); 
    }

Can I please suggest that a code be pasted in GIST or pastebin or whatever places and only share the link here?

  1. Pasting your code here makes it hard to extract and end up spending more time thinking whether we copied it correctly or not

  2. It messes up the entire post and hard to follow up with the problem

  3. The formatting might screw up the original code

Thanks! :wink:

1 Like

@kennethlimcp,

What happen to the wrapper function that allows code to be inserted tin posts ? or have I really lost my mind and it was never used on spark forum ?

@kenneth,

I saw your ghost post in a flash its like it was never there :smile:

---->

@lbruder, here is the code to provide proper code inclusion in to the forum.

This cpp wrapper around code (image):

Produces this code formating:


// This #include statement was automatically added by the Spark IDE.
# include "WebServer.h"

1 Like

Hey guys sorry about that. Here is the spark core code: http://pastebin.com/g00TPfAv
And here is the Rpi Code: http://pastebin.com/kYXYBnYA

Also for anyone curious, here is the csapp.c file: http://pastebin.com/LCkAiRrN.
It just provides two options, buffered and unbuffered I/O. The code is pretty easy to understand.

Also, the debugging log continues to print out the pasted below. Not of much help though:

Tue Jul  1 02:10:21 2014
Opening connection on port: 17060
Tue Jul  1 02:10:51 2014
Method:GET
Option:pi.txt
Opening file: pi.txt
Succuess opening file. Starting to send
Row 0\0

Done sending file

Tue Jul  1 02:11:00 2014
Method:GET
Option:pi.txt
Opening file: pi.txt
Succuess opening file. Starting to send
Row 0\0

Done sending file

Tue Jul  1 02:11:09 2014
Method:GET
Option:pi.txt
Opening file: pi.txt
Succuess opening file. Starting to send
Row 0\0

Done sending file
.....
.....

I believe I have fixed it. I added a delay(100) as soon as we enter the get_response function fixed it!

There is a problem with TCP client in the spark, which manifests itself in the webserver library that not all the data sent from the server reaches the client - adding a delay is currently the only known workaround.

Very strange… Last night I noticed that the more the Raspberry Pi has to send, the more you have to delay in order to receive the whole message