Find the answer to your Linux question:
Results 1 to 7 of 7
Hi again, I have been developing some code which I have been testing an another i386 system. However I have been getting some weird data received on a socket. I ...
  1. #1
    Just Joined!
    Join Date
    Jul 2010
    Posts
    25

    Weird recv() problem, buffer back to front?

    Hi again,

    I have been developing some code which I have been testing an another i386 system. However I have been getting some weird data received on a socket.

    I am communicating with some 3rd party hardware, I have opened a socket to read data on the hardware's telnet port. The data being read is as expected and my code appears to function correctly.

    However I have now began testing the code on a target platform, this platform is of a better spec than my development system. When I read data from the socket using recv(), all the expected data has not been read. A chunk of data from the beginning is missing and a portion of data that would be at the end is now at the beginning of the buffer. I'll try and illustrate this below.

    Code:
    //Expected data in buffer when printed to screen
    1
    2
    3
    4
    5
    6
    Code:
    //What is actually being printed to screen from buffer
    5
    6
    3
    4
    Though the target platform is of a better spec, the biggest difference is that the target platform has DDR3 memory in it. A shot in the dark but could this be an issue?

    Due the buffer being messed up I get random seg faults from strstr calls that perform on the buffer.

    An odd one? Any ideas would be appreciated as I am struggling to debug this.

    Cheers

  2. #2
    Linux Newbie
    Join Date
    Mar 2010
    Posts
    121
    Are you making sure that (i) everything is getting transferred in network byte order and (ii) everything is getting converted to local byte order on the local machine? If these are ASCII characters and you weren't doing this (and the two machines have a different endianness), then the (presumably) expected "0x31323334 0x35360000" (ASCII "123456" with two trailing 0's) might be turned into "0x34333231 0x00003635".

    Check out `man ntohs' for how you can convert between host and network byte order.

  3. #3
    Just Joined!
    Join Date
    Jul 2010
    Posts
    25
    Quote Originally Posted by JohnGraham View Post
    Are you making sure that (i) everything is getting transferred in network byte order and (ii) everything is getting converted to local byte order on the local machine? If these are ASCII characters and you weren't doing this (and the two machines have a different endianness), then the (presumably) expected "0x31323334 0x35360000" (ASCII "123456" with two trailing 0's) might be turned into "0x34333231 0x00003635".

    Check out `man ntohs' for how you can convert between host and network byte order.
    Hmm I see. Though if this were the case, would you expect the buffer on every recv() called to be reversed? This seems to occur randomly.

  4. #4
    Linux Newbie
    Join Date
    Mar 2010
    Posts
    121
    Quote Originally Posted by aManFromOuterSpace View Post
    Hmm I see. Though if this were the case, would you expect the buffer on every recv() called to be reversed? This seems to occur randomly.
    It would only occur if the data received through recv() is 8 bit character data being treated as 32 bit integers at some stage (possibly even before it's sent?). If other places treat is as 8 bit character data they won't see this problem.

    It may not be that, just a thought on something to double-check. Possibly the best thing to do is get a Wireshark trace of the data and see what's actually on the wire.

  5. #5
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    You don't say if you are using the same OS and kernel on both systems. Also, you don't provide any code to see how you are setting up the connection and then using it. Please do so.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  6. #6
    Just Joined!
    Join Date
    Jul 2010
    Posts
    25
    Quote Originally Posted by Rubberman View Post
    You don't say if you are using the same OS and kernel on both systems. Also, you don't provide any code to see how you are setting up the connection and then using it. Please do so.
    Both systems are using 2.6.34.6-54.fc13.i686.

    As for some code here we go, just to reiterate in the function InetTelnetReadUntil when I printf the buffer contents the reordering of the contents can happen randomly.

    Cheers

    Code:
    int InetTelnetOpen(const char *telnetServer, unsigned short remotePort)
    {
        int sd;
        struct sockaddr_in sin;
        int on;
        
        //Create TCP Socket
        sd = socket(AF_INET, SOCK_STREAM, 0);
        if(sd < 0){
            Die("Failed to create socket");
            return -1;
        }
    
        on = 1;
        setsockopt( sd, SOL_SOCKET, MSG_NOSIGNAL, &on, sizeof(on) );
        
        //Consrcut the server sockaddr_in structure
        memset(&sin, 0, sizeof(sin));                   //clear structure
        sin.sin_family = AF_INET;                       //Internet/IP
        sin.sin_addr.s_addr = inet_addr(telnetServer); //IP address
        sin.sin_port = htons(remotePort);
    
        //Establish the connection
        if(connect(sd, (struct sockaddr*)&sin,sizeof(sin))<0){
            Die("Failed to connect to server");
            return -1;
        }
        
        return (sd);
    }
    
    int InetTelnetReadUntil(int hSocket, char *readBuffer, size_t readLength, const char *stringToMatch, unsigned int timeout)
    {
        int j;
        char *pMatchedString = NULL;
    
        memset(readBuffer, 0, readLength);
    
        while(!pMatchedString)
        {
            j = 0;
            
            int bytes = 0;
            bytes = recvtimeout(hSocket, readBuffer, readLength, timeout);
    
            if(bytes==-2){
                Die("Timeout");
                return -2;
            }
    
            if(!bytes){
                Die("No Bytes Read");
                return -3;
            }
    
            pMatchedString = strstr(readBuffer, stringToMatch);
    
            if(pMatchedString)
            {
                system("clear");
                printf("%s\n", readBuffer); //debug: print buffer to visually verify
    
                for(j=0; j<strlen(stringToMatch); j++)
                    pMatchedString++;
    
                pMatchedString[0] = '\0';
            }
    
        }
        return 0;
    }
    
    int recvtimeout(int s, char *buf, size_t len, int timeout)
    {
        fd_set fds;
        int n = 0;
        struct timeval tv;
    
        //set up the file descriptor set
        FD_ZERO(&fds);
        FD_SET(s,&fds);
    
        //set up the struct timeval for the timeout
        tv.tv_sec = timeout;
        tv.tv_usec = 0;
    
        //wait until the timeout or data received
        n = select(s+1, &fds, NULL, NULL, &tv);
        if(!n)      return -2; //timeout
        if(n==-1)   return -1; //error
    
        //data must be here, so do a normal receive
        return recv(s, buf, len, 0);
    }

  7. #7
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    Ok. The code seems, at first glance, to be reasonable. I take it that the 3rd party hardware is a separate piece of equipment on the network? As you are connecting with a TCP, not a UDP socket, then the data should appear to your application in the order sent. It is possible that the ethernet hardware on the newer/faster system is not working correctly. However, if other network connections are working correctly then I would tend to doubt that. Sorry, but at this point I can't think of anything further to consider other than trying on another computer or with another ethernet board to see if that has the same problem.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...