我正在创建一个FTP客户端。
我从服务器获取了一个gif,但之后gif已损坏。
当我更改文件扩展名以查看差异时,我看到了 CR / LF字符消失了。
怎么会这样?我确保使用图像模式。
这是我在TCP套接字中读取的代码。
string TCPSocket::long_read()
{
pollfd ufds;
ufds.fd = sd;
ufds.events = POLLIN;
ufds.revents = 0;
ssize_t bytesRead = 0;
string result;
char* buf = new char[LONGBUFLEN];
do {
bzero(buf, LONGBUFLEN);
bytesRead = ::read(sd, buf, LONGBUFLEN);
if (bytesRead == 0) {
break;
}
if (bytesRead > 0) {
result = result + string(buf, bytesRead);
}
} while (poll(&ufds, 1, 1000) > 0);
return result;
}
这是我在main.cpp中获取代码
else if (command == command::GET) {
string filename;
cin >> filename;
string dataHost;
int dataPort;
if (enterPassiveMode(dataHost, dataPort)) {
dataSocket = new TCPSocket(dataHost.c_str(), dataPort);
if (fork() == 0) {
string result = dataSocket->long_read();
size_t length = result.size();
char* resultArr = new char[length];
memcpy(resultArr, result.data(), length);
// mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
FILE* file = fopen(filename.c_str(), "w+b");
if (file) {
fwrite(resultArr, length, 1, file);
fclose(file);
}
else {
cout << "open failed";
}
break;
}
else {
writeAndImmediateRead(rfc959::TYPE_I);
controlSocket->write(rfc959::RETRIVE(filename));
string result = controlSocket->read();
cout << result;
int reply = Parser::firstDigit(result);
// I'll remove incomplete local file if request fails
if (reply != rfc959::POSITIVE_PRELIMINARY_REPLY) {
remove(filename.c_str());
continue;
}
wait(NULL);
cout << controlSocket->long_read();
}
}
}
我确实使用二进制模式。当我传输一个文本文件(虽然尺寸较小)时,它没有这个问题。这是输出:
Wireshark的输出显示Request: TYPE I
和Response: Opening BINARY mode
答案 0 :(得分:0)
默认情况下,FTP服务器和客户端以&#34; ASCII模式&#34;执行数据传输,这意味着任何CRLF序列都会即时转换到主机的ASCII行结尾(例如在Unix mmachines上只是裸LF)。此行为由RFC 959强制执行;见3.1.1.1节。
要将数据作为二进制文件传输,并避免ASCII模式转换,您的FTP客户端将首先发送TYPE
命令,例如:< / p>
TYPE I
然后应该按原样传输.gif
文件,不对任何CRLF序列进行替换/转换。
希望这有帮助!