For a while, I am troubled with this issue.
Using a snippet of C++ code, which I found here, and in my opinion should do a good job actually sending exact amount of data, I guess the problem is in the Java code or something unknown.
Also, when sending simple "Hello World" data, transfer is done correctly.
I would be grateful is somebody could solve it, or give a valuable advice. I am running Windows 10 with jdk1.8.0_221 and Visual Studio 2022.
I understand there could be a need to send filesize as a string and aknowledge flag in return in future, but for simplicity the C++ client is sending only one file with known amount of data.
Here is the Java side:
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 bytes again after I tried this:
int filesize = 15670;
int cnt = 0;
while (cnt<filesize)
{
out.write(in.read());
out.flush();
cnt++;
}
It makes me think 8 bytes are added while saving.
The C++ code:
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;
}
The C++ code is sending the file size before sending the file data (good), but is not doing adequate error handling (bad), and it is NOT sending the file size in an platform-agnostic format (bad).
Not that it matters, because the Java code shown is NOT even attempting to read the file size before reading the file data (very bad), nor is it paying attention to the return value of
in.read()to know how many bytes are actually received. But even if it were, the C++ code is sending the size as an 8-byte integer (needed for large files > 2GB), but the Java code is using a 4-byte integer instead (bad). The C++ is also using a 4-byte integer forbytes_sentinSendFile().Try something more like this: