Я использую TCP-сервер, который я написал для обработки входных данных в базу данных. У меня есть клиент TCP, сидящий на сервере, который отправляет имя файла на сервер TCP, сидящий на другом сервере Linux. Как только имя файла получено, сервер Linux переходит в общую папку и извлекает файл, а затем вставляет его в базу данных.
Моя проблема заключается в том, чтобы правильно объявить буфер и очистить его, чтобы убедиться, что я получаю правильное имя файла без каких-либо добавленных трюков или удаления чего-либо из него.
сейчас это работает так:
char data[1024];
это нормально, но он не удаляет буфер полностью автоматически, поэтому я попытался неявно выделить память для «данных», таких как:
char *data = (char*) malloc(1024 * sizeof(char));
...
free(data);
ИЛИ ЖЕ
char *data = new char[1024];
...
delete[] data;
По какой-то причине вышеупомянутые две декларации объявляют буфер размером = 8, я получил это, используя
sizeof(data);
Кроме того, я получаю только 8 символов. Я не уверен, почему он делает это, любая помощь?
РЕДАКТИРОВАТЬ
char *data = (char*)malloc(1048 * sizeof(char));
if(data==NULL) exit(1);
cout << "DATA Size: " << sizeof(data) << "\n";
int msglen = read(conn, data, sizeof(data));
cout << "Server got " << msglen << " byte message: " << data << "\n";
if(write(conn, &msglen, sizeof(msglen))<0){
cout << "Failed to write back to the client " << strerror(errno);
}
free(data);
close(conn);
Есть несколько вещей не так с вашим кодом.
1) не используйте malloc — вы пометили свой вопрос как c ++ — используйте malloc только при необходимости, замените его на:
const int dataSize = 1024;
char *data = new char[dataSize];
2) sizeof (data), когда data является char *, возвращает 8, потому что он возвращает размер указателя, а не массива, когда вы объявляете данные как массив sizeof будет возвращать байты, занятые всем массивом. вам следует заменить прочитанное на:
int msglen = read(conn,data,dataSize)
3) Я предполагаю, что вы хотите записать данные, которые вы только что получили обратно отправителю. Затем:
в функции записи вы помещаете sizeof (msglen) в качестве третьего аргумента, который (в большинстве случаев) всегда возвращает 4. remove sizeof ().
write(conn, data, msglen);
После того, как вы закончите с данными, не забудьте очистить память, используя:
delete[] data;
использование delete[]
всегда, когда вы назначили память new[]
,
API write(int socket, char *buf, int len)
;
Код становится таким:
write(con, data, msglen);
Предполагая, что вы не можете использовать стек (например, char buf[1024]
), использование голых указателей не рекомендуется как плохой стиль и подвержены ошибкам. Вместо этого используйте RAII и некоторый вариант измененной памяти, такой как shared_ptr
или же unique_ptr
,
#include <memory>
и использовать std::shared_ptr<>
, или же std::unique_ptr<>
плюс std::move()
вернуть буфер:
std::size_t bufSize = 1024;
std::unique_ptr<char[]> myUniqueBuf(new char[bufSize]);
ssize_t msglen = ::read(conn, *myUniqueBuf, bufSize); // return type is ssize_t, not int
return std::move(myUniqueBuf); // If you need to return the buffer
// I think you will probably prefer a shared_ptr<> because it has a copy
// constructor which makes it easier to pass around and return from functions
std::shared_ptr<char[]> mySharedBuf(new char[1024]);
ssize_t msglen = ::read(conn, *mySharedBuf, bufSize); // return type is ssize_t, not int
ssize_t bytesOut = ::write(conn, *mySharedBuf, msglen);
return mySharedBuf;
Преимущество для std::shared_ptr
или же std::unique_ptr
в том, что вам не нужно беспокоиться об очистке голого указателя (т.е. delete[] data;
) потому что с управляемой памятью это будет происходить автоматически для вас, когда дескриптор буфера выходит из области видимости или счетчик ссылок обнуляется (например, myUniqueBuf
или же mySharedBuf
).