Click here to Skip to main content
14,773,758 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
My struct:
typedef enum {
    SEND_FILE       =   0,
    FILE_SIZE       =   10,
}CommandList;

typedef struct {
    CommandList command;
    char DataBuffer[PAYLOAD_SIZE];
} COMMAND_HEADER;

struct Command_Data {
    char message;
};

void some_unnamed_function() {
   ...
   COMMAND_HEADER command_header;
   command_header.command = SEND_FILE;
   ULONGLONG dwLength = Sourcefile.GetLength();
   char* buffer = new char[(int)dwLength + 1];
   buffer[dwLength] = 0;
   UINT nActual = Sourcefile.Read(buffer, dwLength);
   Command_Data *tmp_str = (Command_Data *)buffer;
   //Buffer contains text file. 
   int nfRet = SockConnection.Send((char*)&command_header, sizeof(command_header));

   //Command_Data *tmp_str = (Command_Data *)buffer;//trying to type cast from char* to struct.

   ...
}

I'm transferring file through structure command in CSocket. But, not sure char* to struct is correct. Pls make this right.

What I have tried:

UINT nActual = Sourcefile.Read(buffer, dwLength);
//Buffer contains text file.

Command_Data *tmp_str = (Command_Data *)buffer;

int nfRet = SockConnection.Send((char*)&command_header, sizeof(command_header));
Posted
Updated 14-Dec-20 14:50pm
v2
Comments
Stefan_Lang 28-Jan-19 5:16am
   
The code you posted is incomplete, and leaves us guessing what is missing or wrong.
At the very least, I can't see a declaration of the variable, command_header.

There's also one probable error int the struct Command_Data: the member variable message is declared as type char - shouldn't it be an array of or pointer to char instead? it's hard to tell what your intention was.
rmds 28-Jan-19 5:35am
   
My bad! I missed these...
COMMAND_HEADER command_header;
command_header.command = SEND_FILE;
ULONGLONG dwLength = Sourcefile.GetLength();
char* buffer = new char[(int)dwLength + 1];
buffer[dwLength] = 0;
UINT nActual = Sourcefile.Read(buffer, dwLength);
Command_Data *tmp_str = (Command_Data *)buffer;
//Buffer contains text file.
int nfRet = SockConnection.Send((char*)&command_header, sizeof(command_header));

//Command_Data *tmp_str = (Command_Data *)buffer;//trying to type cast from char* to struct.
Stefan_Lang 28-Jan-19 5:51am
   
This helps somewhat, but you should add the full code in your original posting, using the green [improve question] link at the bottom right of your question.

I'm going to do it for you, this time, and I will add code tags for readability while I'm at it...
rmds 28-Jan-19 6:08am
   
Thank you, but the code posted already is pretty much all of it.
By the way I found way to type cast from char* to struct.

"Command_Data* tmp_str = reinterpret_cast<Command_Data*>(buffer);"
Now, gotta copy this data into [Command_Data message buffer]. I changed it to array.. How to do this?

There are several problem I see with your code.

1. Your variable, command_header, is not initialized completely: only the command is assigned, but you never fill its DataBuffer. Did you mean to read the data from SourceFile into that buffer? If so, you need to copy it from buffer, and make sure you're not exceeding the PAYLOAD_SIZE.

2. The definition of Command_Data seems wrong. It only contains one char the way it's declared in your code. It's not clear what this struct is supposed to be, and used for.

3. tmp_str is never used. Therefore it's hard to say whether that assignment makes sense, or how to improve it.

Generally speaking, the compiler will normally accept all C-style typecasts, but that doesn't mean they make sense, or won't crash your program at run-time. I would suggest an alternative, but for that I need to know the use of tmp_str in your program.

P.S.:
After much additional info, and making some educated guesses, I think this is what your code should look like:
enum Command {
   SEND_FILE       =   0,
   FILE_SIZE       =   10,
};
struct FileSizeMsg {
   Command command;
   int file_size;
};
struct FileSendMsg {
   Command command;
   char data[]; // see below
};
int send_text_file(CFile& Sourcefile) {

   // get size of file
   ULONGLONG dwLength = Sourcefile.GetLength();
   // read file into buffer
   char* buffer = new char[(int)dwLength + 1];
   UINT nActual = Sourcefile.Read(buffer, dwLength);
   buffer[dwLength] = 0; // just in case Read() does not add a terminating 0-byte
   // find out real string length
   size_t real_length = strlen(buffer);

   // prepare first message: the file size
   FileSizeMsg size_msg;
   size_msg.command = FILE_SIZE;
   size_msg.file_size = (int)real_length;
   // send file size message
   int nfRet = SockConnection.Send((char*)&size_msg, sizeof(size_msg));

   // second message: the actual data
   // dynamically allocate a sufficiently large memory block
   int full_length = (int)sizeof(Command) + real_length + 1;
   char* full_message = new char[full_length];
   // reuse that memory block as a FileSendMsg object and fill its data members
   FileSendMsg* send_msg = reinterpret_cast<FileSendMsg*>(full_message);
   send_msg->command = SEND_FILE; // this assignment writes to the first byte(s) of full_message
   strncpy(send_msg->data, buffer, real_length + 1);
   // now send the full memory block
   nfRet = SockConnection.Send(full_message, full_length);

   delete [] buffer;
   delete [] full_message;
   return nfRet;
}

This assumes that the receiver of these messages expects a size info message separated from the actual data. (otherwise why introduce two different commands?).

Note how FileSendMsg.data is declared as a placeholder for a string of arbitrary length. It can not be used in a normal way, but if you separate the memory allocation from the use of this struct, it behaves like a dynamically sized object class.
   
v2
Comments
rmds 28-Jan-19 7:04am
   
command_header is an object structure Command_Data. and Yes, I'm reading the data from SourceFile into that buffer. I also changed the definition of command data to:

struct Command_Data {
char message[1000];
};

All I want is copy the buffer which contains data from file into this 'char message[1000]' in above struct.
Stefan_Lang 28-Jan-19 9:29am
   
You could use memcpy:
mempy(comand_header.DataBuffer, buffer, std::min(1000, nActual));

See http://www.cplusplus.com/reference/cstring/memcpy/

If the data type is actually text, you could use strncpy instead.
rmds 28-Jan-19 13:39pm
   
Thanks much...Somehow this memcpy reads garbage values too at the end...Here's what I tried:
memcpy(command_header.Message_Buffer, buffer, /*min(1000, nActual)*/nActual);
buffer[nActual] = '\0';
int nRet = m_SocketConnection.Send((char*)&command_header,
sizeof(command_header));
Stefan_Lang 29-Jan-19 3:18am
   
If the file contains text, you need strncpy rather than memcpy - same syntax, but strncpy will automatically stop at the 0-terminator. Also, you may need to add a 0 byte to the target buffer at the end, in case it isn't read from the file. See http://www.cplusplus.com/reference/cstring/strncpy/ for documentation and a code example.
Stefan_Lang 29-Jan-19 3:23am
   
P.S.: assuming nActual is smaller than 1000, you should maybe reduce the size of the message you send in that last line from sizeof(command_header) to sizeof(command_header)-1000+nActual+1
(+1 for terminating 0 byte)

That way you will not send garbage bytes past the end of the actual text.
Stefan_Lang 30-Jan-19 7:21am
   
P.P.S.: I updated my solution with a code example. It should work as is, except that it's lacking the declaration of SockConnection.
You do not need a struct in either case. Your command header is a single value (byte?) which you transmit on its own, followed by a character buffer read from the input file. You also need to modify your read code as you are doing things in the wrong order. It should be:
typedef enum {
    SEND_FILE       =   0,
    FILE_SIZE       =   10,
}CommandList;

void some_unnamed_function() {

    CommandList command;
    char *DataBuffer;
    
   command = SEND_FILE;
   ULONGLONG dwLength = Sourcefile.GetLength();
   DataBuffer = new char[(int)dwLength + 1];
   UINT nActual = Sourcefile.Read(buffer, dwLength);
   DataBuffer[nActual] = 0;
   //Buffer contains text file. 
   int nfRet = SockConnection.Send((char*)&command, sizeof(command));
   nfRet = SockConnection.Send(DataBuffer, nActual);


   ...
}
   
To cast a struct to char* buffer you need to allocate buffer of the sizeof struct. Then you can use memcpy while casting the struct to the char*

An example:

struct blah
{
    int i;
    float f;
};

blah b = {10, 2.75};
char buffer[8]; // sizeof(blah) == 8

memcpy(buffer, (char*)&b, sizeof(blah));
   
v2
Comments
rmds 29-Jan-19 1:34am
   
Actually mine is char* to struct. Tried:
method 1. memcpy(command_header.Message_Buffer, buffer, nActual);
buffer[nActual] = '\0';

method 2. memset(command_header.DataBuffer, '\0', sizeof(command_header.DataBuffer));
strcpy(command_header.DataBuffer, buffer);

Both these methods reads data along with junk values too.
steveb 29-Jan-19 8:35am
   
When you copying character array into struct you do it to the struct's pointer, assuming your char array contains entire structure i.e.

struct blah b;
memcpy(&b, buffer, sizeof(blah));
Type casting doesnt mean the code becomes more valid or better. It is more that every type cast makes your code more dangerous and problematic.

You must provide enough memory and work with it correctly. Imagine pointers as address to some memory. If the memory isnt valid it will crash sooner or later!!!.
   
Comments
rmds 28-Jan-19 23:26pm
   
Agreed! Pls help me get rid of garbage values in above situation. Thank you
My solution is to use a union :

typedef struct {
double value1;
long value2;
} t_myStruct;

typedef union {
unsigned char asChar[sizeof(t_myStruct)];
t_myStruct data;
} t_myData;

t_myData mydata;

then assign values to mydata.data.value1 and mydata.data.value2

When you want to send it by serial port, simply refer mydata.asChar

No need to copy and no overhead cost.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900