我正在编写文件传输客户端/服务器应用程序 客户端在windows7上运行并在vb.net中编写 并且服务器在linux mint上运行并用c ++编写(我使用的是vmware) 我的问题是,当我尝试将文件上传到服务器(如图像)时,收到的数据丢失了许多字节,这些字节也代表控制字符(例如EOT,ETB,...),我想它们被读作tcp控制字符并被接收操作系统忽略。 我已经使用简单的文本文件(大小高达4MB)测试了应用程序,没有任何问题。 有没有办法阻止系统忽略这些字节?
这是接收文件的c ++函数:
string readSockBytes(int port,int num,int size)
{
int dcmbuffSize = 1460;
int n;
stringstream temp;
string strBuffer,Sbuffer;
char Rbuffer[dcmbuffSize];
struct socketVar sockets;
sockets = setSocket(port);
sockets = sockListen(sockets);
cout<<"user connected\n";
strBuffer = readsock(sockets);
cout<<strBuffer.substr(0,strBuffer.find("$"))<<endl;
if(num == atoi(strBuffer.substr(0,strBuffer.find("$")).c_str()))
Sbuffer = "ready$";
else
{
Sbuffer = "exit$";
close(sockets.newsockfd);
close(sockets.sockfd);
}
n = writesock(sockets, Sbuffer, 100);
if (n < 0) error("ERROR writing to socket");
while(strBuffer.length() < fileSize)
{
n = read(sockets.newsockfd,Rbuffer,dcmbuffSize-1);
if (n < 0) error("ERROR reading from socket");
temp.str(Rbuffer);
strBuffer = strBuffer+temp.str();
}
strBuffer = strBuffer.substr(0,size);
return strBuffer;
}
答案 0 :(得分:1)
问题很可能是您发送了二进制数据。二进制数据可以包含零。并且零是正常的字符串终止符。
这意味着当您执行temp.str(Rbuffer)
时(假设temp
是std::stringstream
),那么它只会从Rbuffer
获取数据直到第一个零。
而不是使用例如std::stringstream
使用std::string
:
while(strBuffer.length() < fileSize)
{
char buffer[2048];
ssize_t n = read(sockets.newsockfd, buffer, sizeof(buffer));
if (n <= 0)
{
// An error, or connection closed
if (n < 0)
error("ERROR reading from socket");
break;
}
// Create a string of `n` bytes, including possible string terminators
// and add it to out current buffer
strBuffer += std::string(buffer, n);
}
这里要记住的重要一点是,不能将收到的数据用作字符串!如果它是二进制数据,它将最确定地包含字符串终止符,因此您必须将其视为二进制数据而不是字符串(即使您可以将其存储在std::string
中)。
您还需要注意,您无法打印数据,因为许多二进制值要么不可打印,要么打印为“垃圾”。
最后,如果你读写二进制文件,你需要以二进制模式打开它们,否则你会得到字节0x0d
和0x0a
的错误(即回车和换行)