有一段時間,我為這個問題而煩惱。
使用我在這里找到的一段 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;
}
uj5u.com熱心網友回復:
C 代碼在發送檔案資料之前發送檔案大小(好),但沒有進行足夠的錯誤處理(壞),并且它沒有以與平臺無關的格式發送檔案大小(壞)。
這并不重要,因為顯示的 Java 代碼甚至沒有嘗試在讀取檔案資料之前讀取檔案大小(非常糟糕),也沒有注意回傳值in.read()以了解實際接收到的位元組數。但即使是這樣,C 代碼也將大小作為 8 位元組整數發送(對于大于 2GB 的大檔案需要),但 Java 代碼使用的是 4 位元組整數(不好)。C 還為bytes_sentin使用 4 位元組整數SendFile()。
嘗試更多類似的東西:
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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/422251.html
標籤:
上一篇:檢查物件是否與已知型別串列匹配
下一篇:Java通過httpclient使用restfulapi。JacksonjsonMismatchedInputException遇到問題
