Рейтинг:
32
Stefan_Lang
Есть несколько проблем, которые я вижу с вашим кодом.
1. Ваша переменная command_header не инициализируется полностью: назначается только команда, но вы никогда не заполняете ее буфер данных. Вы хотели прочитать данные из исходного файла в этот буфер? Если это так, вам нужно скопировать его из буфера и убедиться, что вы не превышаете PAYLOAD_SIZE.
2. Определение Command_Data кажется неправильным. Он содержит только один символ так, как он объявлен в вашем коде. Непонятно, для чего эта структура предназначена и используется.
3. tmp_str никогда не используется. Поэтому трудно сказать, имеет ли это назначение смысл или как его улучшить.
Вообще говоря, компилятор обычно принимает все типы C-стиля, но это не значит, что они имеют смысл или не приведут к сбою вашей программы во время выполнения. Я бы предложил альтернативу, но для этого мне нужно знать использование tmp_str в вашей программе.
С. П.:
После большого количества дополнительной информации и некоторых обоснованных предположений я думаю, что именно так должен выглядеть ваш код:
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;
}
Это предполагает, что получатель этих сообщений ожидает сообщение информации о размере, отделенное от фактических данных. (иначе зачем вводить две разные команды?).
Обратите внимание, как FileSendMsg.data объявляется в качестве заполнителя для строки произвольной длины. Его нельзя использовать обычным способом, но если вы отделите выделение памяти от использования этой структуры, он будет вести себя как класс объектов с динамическим размером.
rmds
command_header-это структура объекта Command_Data. и да, я читаю данные из исходного файла в этот буфер. Я также изменил определение командных данных на:
структура Command_Data {
сообщение char[1000];
};
Все, что я хочу, это скопировать буфер, содержащий данные из файла, в это " char message[1000]" в приведенной выше структуре.
Stefan_Lang
Вы можете использовать memcpy:
mempy(comand_header.DataBuffer, буфер, std::min(1000, nActual));
Видишь ли http://www.cplusplus.com/reference/cstring/memcpy/
Если тип данных на самом деле текстовый, то вместо него можно использовать strncpy.
rmds
Большое спасибо...Каким-то образом этот memcpy тоже читает мусорные значения в конце...вот что я попробовал:
memcpy(command_header.Message_Buffer, буфер, /*min(1000, nActual)*/nActual);
буфер[nActual] = '\0';
int nRet = m_SocketConnection.Send((char*)&command_header,
оператор sizeof(command_header));
Stefan_Lang
Если файл содержит текст, вам нужен strncpy, а не memcpy - тот же синтаксис, но strncpy автоматически остановится на 0-Терминаторе. Кроме того, вам может потребоваться добавить 0 байт в целевой буфер в конце, если он не будет считан из файла. Видишь ли http://www.cplusplus.com/reference/cstring/strncpy/ для документации и примера кода.
Stefan_Lang
P.S.: предполагая, что nActual меньше 1000, вам, возможно, следует уменьшить размер сообщения, которое вы отправляете в этой последней строке, с sizeof(command_header) до sizeof(command_header)-1000+nActual+1
(+1 для завершения 0 байт)
Таким образом, вы не будете отправлять мусорные байты за конец фактического текста.
Stefan_Lang
P. P. S.: Я обновил свое решение с помощью примера кода. Он должен работать как есть, за исключением того, что в нем отсутствует объявление SockConnection.
Рейтинг:
26
Richard MacCutchan
В любом случае вам не нужна структура. Заголовок вашей команды-это одно значение (байт?) который вы передаете самостоятельно, а затем буфер символов считывается из входного файла. Вам также необходимо изменить свой код чтения, поскольку вы делаете вещи в неправильном порядке. Так и должно быть:
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);
...
}
Рейтинг:
2
steveb
Чтобы привести структуру к char* buffer, вам нужно выделить буфер структуры sizeof. Затем вы можете использовать memcpy при приведении структуры к символу char*
Пример:
struct blah
{
int i;
float f;
};
blah b = {10, 2.75};
char buffer[8]; // sizeof(blah) == 8
memcpy(buffer, (char*)&b, sizeof(blah));
rmds
На самом деле мой-это char* to struct. Пытался:
метод 1. memcpy(command_header.Message_Buffer, буфер, nActual);
буфер[nActual] = '\0';
метод 2. memset(command_header.DataBuffer, '\0', sizeof(command_header.Databuffer, с));
strcpy(command_header.Буфер данных, буфер);
Оба этих метода также считывают данные вместе с ненужными значениями.
steveb
Когда вы копируете массив символов в структуру, вы делаете это с указателем структуры, предполагая, что Ваш массив символов содержит всю структуру, т. е.
структура бла б;
memcpy(&b, buffer, sizeof(бла));
Рейтинг:
2
KarstenK
Приведение типов не означает, что код становится более валидным или лучшим. Более того, каждый приведенный тип делает ваш код более опасным и проблематичным.
Вы должны предоставить достаточно памяти и работать с ней правильно. Представьте, что указатели адресов в памяти. Если память не является действительной, она рухнет рано или поздно!!!.
rmds
Согласен! Пожалуйста, помогите мне избавиться от мусорных значений в вышеуказанной ситуации. Спасибо