Thread: Character array substring.

  1. #1
    Registered User
    Join Date
    Aug 2006
    Posts
    28

    Character array substring.

    I have written a program that communicates with a server via sockets. To make my life easier I created a 'socket' class which takes care of all the low-level socket stuff. One of the methods is called 'send' and you'd never guess, but it handles the sending of data. Because I will sometimes be using it for large packets, I have implemeted a way of making sure all data is sent before it returns. Right now it accepts a string, sends what it can, and then loops until it has sent the rest.

    Unfortunately I can no longer use the handy std::string class for this method. Some of my data must be sent as an 8 byte character array, which is picked up as two 4-byte __int32 values at the other end. When converted to a string, this data is somehow corrupted and not read properly by the server. It must be sent as a char type and must have measures in place to ensure all data is sent.

    Right now, this is what it looks like..
    Code:
    //Sends a string of data
    void SockWrap::sSend(std::string data){
    
        //Initialise variables
        int bytes_sent = 0;
        int total = 0;
        //Get length of data in bytes..
        int len = data.length();
        
        //Loop until all data has been sent..
        while (total < len) {
        
            //Send data...
            //If statement checks for errors. -1 is returned by send() if error occurs..
            if ((bytes_sent+=send(this->sockfd, data, data.length(), 0)) == -1){
                 std::cout << "Error sending data!" << std::endl;
                 system("PAUSE");  
                 exit(1);
            }
            total += bytes_sent;
            //Removes data just sent from the data string..
            data = data.substr(bytes_sent, data.length()-bytes_sent);
    
        }
    }
    As you can see, right now it makes use of the substr() method of the string class. I have scoured google for the past hour looking for a way of doing the same thing with a character array, but havent found anything

    Anyone have any ideas how I might solve this?

  2. #2
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    sub_str() into a temp std::string, and then c_str() that to a character array, if ya get me

  3. #3
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Still no need to use a character array. Use c_str(). It will convert your substring into a C-style string.

    http://www.cppreference.com/cppstring/c_str.html
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  4. #4
    Registered User
    Join Date
    Aug 2006
    Posts
    28
    I cannot use std::string at all for some reason. When I do it somehow corrupts the 8-bytes and all communication with the server breaks down.

    One other thing, the code I posted above it slightly incorrect due to my messing around with it. It should be..
    Code:
    if ((bytes_sent+=send(this->sockfd, data.c_str(), data.length(), 0)) == -1){
    ..due to the fact that send() can only take character arrays.

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    what's the prototype of the send function?
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Registered User
    Join Date
    Aug 2006
    Posts
    28
    According to this its..
    Code:
    int send(int sockfd, const void *msg, int len, int flags);
    However if I pass anything other than char the compiler will give me..
    Code:
    94 C:\xmlgbx\gbx\socketwrap.cpp cannot convert `xxxx' to `const char*' for argument `2' to `int send(SOCKET, const char*, int, int)'
    So I think that website is mistaken. Either that or its a limitation of winsock.

  7. #7
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Well I'm sorry. I cannot help past this.

    I find it strange that c_str() would give you trouble. c_str() returns a const char*, which more than well fits into const void*.

    Somebody else will be able to help i'm sure
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    As an aside, are you sure you want += here?
    Code:
            //If statement checks for errors. -1 is returned by send() if error occurs..
            if ((bytes_sent+=send(this->sockfd, data, data.length(), 0)) == -1){
                 std::cout << "Error sending data!" << std::endl;
                 system("PAUSE");  
                 exit(1);
            }
            total += bytes_sent;
    If bytes_sent is say 4 and send returns -1, no error is detected.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  9. #9
    Registered User
    Join Date
    Aug 2006
    Posts
    28
    Quote Originally Posted by Mario F.
    Well I'm sorry. I cannot help past this.

    I find it strange that c_str() would give you trouble. c_str() returns a const char*, which more than well fits into const void*.

    Somebody else will be able to help i'm sure
    Its not that I cant pass strings to send()

    The problem is that i'm trying to pass a specific 8-byte 'header' packet. This has to be done correctly so that the server can pick it up and split it into two 4-byte int32 values, one being the size of the 'body' packet, and the other a handle for asynchronous communication. I can package this header into a character array no problem, but if I convert that to a string and pass it to send(), for some reason it isnt picked up correctly at the other end.

    If I send the char* value as it is without converting to a string it works perfectly. Unfortunately this isnt very safe as send() doesnt always send the entire thing. Its up to the coder to ensure any stray bytes are sent. That is why I need a method of passing any un-sent bytes to send(), while keeping them as char type.

    But thanks anyways

  10. #10
    Registered User
    Join Date
    Aug 2006
    Posts
    28
    Quote Originally Posted by Dave_Sinkula
    As an aside, are you sure you want += here?
    Code:
            //If statement checks for errors. -1 is returned by send() if error occurs..
            if ((bytes_sent+=send(this->sockfd, data, data.length(), 0)) == -1){
                 std::cout << "Error sending data!" << std::endl;
                 system("PAUSE");  
                 exit(1);
            }
            total += bytes_sent;
    If bytes_sent is say 4 and send returns -1, no error is detected.
    I wouldnt normally have the += but i've been messing around with the code and forgot to switch it back properly.

  11. #11
    Registered User
    Join Date
    Aug 2006
    Posts
    28
    I think I could solve this using a for loop. However I would need to know how to empty and resize a character array. Here is a quick sketch of what I was thinking of doing...

    Code:
    //Sends a string of data
    void SockWrap::sSend(char* data){
    
        //Initialise variables
        int bytes_sent = 0;
        int total = 0;
        char temp = *data;
        int i, x;
    
        //Get length of data in bytes..
        int len = sizeof(data);
        
        //Loop until all data has been sent..
        while (total < len) {
        
            //Send data...
            //If statement checks for errors. -1 is returned by send() if error occurs..
            if ((bytes_sent=send(this->sockfd, &temp, sizeof(temp), 0)) == -1){
                 std::cout << "Error sending data!" << std::endl;
                 system("PAUSE");  
                 exit(1);
            }
            total += bytes_sent;
    
            //Empty temp array..
            empty(temp); //????
            
            //Reset x..
            x = 0;
            
            //Fill temp with remaining data...
            for (i = total; i < sizeof(dat)-bytes_sent; i++) {
                temp[x] = *dat[i];
                x++;
            }
    
        }
    }
    However I dont know what should be in place of empty(temp) and the compiler doesnt like the line..
    Code:
    temp[x] = *data[i];
    To which it replies..
    Code:
    85 C:\xmlgbx\gbx\socketwrap.cpp invalid types `char[int]' for array subscript
    Any ideas?

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The Winsock and POSIX sockets send() and recv() prototypes unfortunately differ in their prototypes. POSIX uses (const) void* for the data parameter, Winsock (const) char*.

    I recommend using a higher-level abstraction like Boost.ASIO, POCO, or ACE for networking.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #13
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    Quote Originally Posted by megatron09
    I think I could solve this using a for loop. However I would need to know how to empty and resize a character array. Here is a quick sketch of what I was thinking of doing...

    }[/code]
    However I dont know what should be in place of empty(temp) and the compiler doesnt like the line..
    Code:
    temp[x] = *data[i];
    To which it replies..
    Code:
    85 C:\xmlgbx\gbx\socketwrap.cpp invalid types `char[int]' for array subscript
    Any ideas?
    First, you can't resize a character array,, in the traditional sense of an array. Use std::string if you want to do resize() and clear() functions.

    Second, if data is a character pointer using the subscript operator [] is already de-referencing it. Unless data was an array of pointers (a pointer to a pointer) you can't de-reference it twice.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 05-29-2009, 07:25 PM
  2. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  3. Converting character array to integer array
    By quiet_forever in forum C++ Programming
    Replies: 5
    Last Post: 04-02-2007, 05:48 AM
  4. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  5. Character Array - almost? works
    By voltson4 in forum C Programming
    Replies: 3
    Last Post: 03-04-2003, 06:03 PM