C++客户端套接字发送原始文件和文件大小,Java客户端总是多获得8个字节.即使在强制限制为-8字节后,文件也无法读取



有一段时间,我一直被这个问题困扰着。

使用我在这里找到的C++代码片段,在我看来应该能很好地发送准确的数据量,我想问题出在Java代码或未知的东西上。

此外,当发送简单的"Hello World"数据时,传输是正确的。

如果有人能解决这个问题,或者给我一个宝贵的建议,我将不胜感激。我正在使用jdk1.8.0_221和Visual Studio 2022运行Windows 10。

我知道将来可能需要将filesize作为字符串和确认标志发送,但为了简单起见,C++客户端只发送一个具有已知数据量的文件。

这是Java方面:

while(!Terminate)
{    
byte[] bytes = new byte[1];//code was different for a real buffer 
//...still +8 bytes
while (in.available() > 0) 
{
in.read(bytes);
out.write(bytes);
out.flush();
}
}
out.close();
  • 8个字节后,我再次尝试:
int filesize = 15670;
int cnt = 0;
while (cnt<filesize)
{
out.write(in.read());
out.flush();
cnt++;
}

这让我觉得在保存时添加了8个字节。

C++代码:

int SendBuffer(SOCKET s, const char* buffer, int bufferSize, int chunkSize = 4 * 1024) {
int l = -1;
int i = 0;
while (i < bufferSize) 
{
int l = send(s, &buffer[i], __min(chunkSize, bufferSize - i), 0);
//int l = send(s, &buffer[i], bufferSize , MSG_DONTROUTE);
int j = 0;
std::cout << i << std::endl;
while (l < 0) { Beep(433, 1000); j++; std::cout << "shiban l" << l << std::endl; l = send(s, &buffer[i], __min(chunkSize, bufferSize - i), 0); } // this is an error
i += l;
}
return i;
}
int64_t SendFile(SOCKET s, const std::string fileName, int chunkSize) {
const int64_t fileSize = GetFileSize(fileName);
if (fileSize < 0) { return -1; }
std::ifstream file(fileName, std::ifstream::binary);
if (file.fail()) { return -1; }
if (SendBuffer(s, reinterpret_cast<const char*>(&fileSize),
sizeof(fileSize)) != sizeof(fileSize)) {
return -2;
}
char* buffer = new char[chunkSize];
bool errored = false;
int64_t i = fileSize;
auto bytes_sent = 0;
while (i > 0) {
const int64_t ssize = __min(i, (int64_t)chunkSize);
if (!file.read(buffer, ssize)) { errored = true; break; }
const int l = SendBuffer(s, buffer, (int)ssize);
bytes_sent += l;
int bi = 0;
if (l < 0) { std::cout <<" err :"<< l<<std::endl; errored = true; break; }
i -= l;
}
delete[] buffer;
file.close();
std::cout << "bytes_sent:" << bytes_sent << std::endl;
return errored ? -3 : fileSize;
}

C++代码在发送文件数据之前先发送文件大小(好(,但没有进行足够的错误处理(坏(,并且没有以与平台无关的格式发送文件大小。

这并不重要,因为显示的Java代码甚至没有在读取文件数据之前尝试读取文件大小(非常糟糕(,也没有注意in.read()的返回值来了解实际接收到的字节数。但是,即使是这样,C++代码也会将大小发送为8字节整数(对于大于2GB的大型文件需要(,但Java代码使用的是4字节整数(不好(。C++还在SendFile()中为bytes_sent使用4字节整数。

试试类似的东西:

BufferedInputStream bis = new BufferedInputStream(in);
DataInputStream dis = new DataInputStream(bis);
long filesize = dis.readLong();
if (filesize > 0)
{
byte[] bytes = new byte[4*1024];
do
{
int chunkSize = (int) Math.min(filesize, (long) bytes.length);
dis.readFully(bytes, 0, chunkSize);
out.write(bytes, 0, chunkSize);
out.flush();
filesize -= chunkSize;
}
while (filesize > 0);
}
out.close();
bool SendBuffer(SOCKET s, const char* buffer, int bufferSize) {
while (bufferSize > 0)
{
int numSent = send(s, buffer, bufferSize, 0/*MSG_DONTROUTE*/);
if (numSent < 0) {
Beep(433, 1000);
return false;
}
}
return true;
}
int64_t SendFile(SOCKET s, const std::string fileName, int chunkSize) {
const int64_t fileSize = GetFileSize(fileName);
if (fileSize < 0) { return -1; }
std::ifstream file(fileName, std::ifstream::binary);
if (file.fail()) { return -1; }
const int64_t tmp = htonll(fileSize); // see https://stackoverflow.com/questions/3022552/
if (!SendBuffer(s, reinterpret_cast<const char*>(&tmp), sizeof(tmp))) {
return -2;
}
std::vector<char> buffer(chunkSize);
bool errored = false;
int64_t bytes_sent = 0;
while (fileSize > 0) {
int ssize = static_cast<int>(std::min<int64_t>(fileSize, chunkSize));
if (!file.read(buffer.data(), ssize)) { errored = true; break; }
if (!SendBuffer(s, buffer.data(), ssize)) { errored = true; break; }
fileSize -= ssize;
}
file.close();
if (errored) {
std::cout << "err" << std::endl;
return -3;
}
std::cout << "bytes_sent:" << bytes_sent << std::endl;
return bytes_sent;
}

相关内容

最新更新