I am learning boost::asio network programming and tried to make simple file transfer exercise, using blocking sockets, and so, stuck upon strange issue issue.
Server (receiver) loop is following:
while (true){
int bufSize{ static_cast<int>(pow(2, 18)) };
char* buf{ new char[bufSize] };
__int64 currPos{ 0 };
__int64 fileSize;
std::string fileName;
mSocket->receive(buffer(buf, bufSize)); // here we get pre-defined packet with XML
ParseDescXML(std::string{ buf }, &fileName, &fileSize); // and parse this XML, get name and size
std::ofstream ofs(mSavePath + fileName, std::ios::binary);
if (ofs.is_open()){
while (currPos != fileSize) {
if (bufSize > fileSize - currPos){
delete[] buf;
bufSize = fileSize - currPos;
buf = new char[bufSize];
}
mSocket->receive(buffer(buf, bufSize));
ofs.write(buf, bufSize);
currPos += bufSize;
std::cout << "SERVER " << currPos << std::endl;
}
}
delete[] buf;
ofs.close();
slDebug("Receive completed"); // output some stuff, not related to issue
}
client (sender) loop is following:
mWorkerOccupied = true;
std::ifstream ifs(filePath, std::ios::binary);
if (!ifs.is_open()){
mWorkerOccupied = false;
return false;
}
mFileName = filePath.substr(filePath.find_last_of('\\') + 1, filePath.length());
mCurrPos = 0;
mFileSize = GetFileSize(&ifs);
std::string xmlDesc{ MakeXMLFileDesc(mFileName, mFileSize) }; // here we make XML description
xmlDesc.push_back('\0');
int bufSize{ static_cast<int>(pow(2, 18)) };
char* buf{ new char[bufSize] };
mSocket->send(buffer(xmlDesc.c_str(), bufSize)); // and send it.
while (mCurrPos != mFileSize){
if (bufSize > mFileSize - mCurrPos){
delete[] buf;
bufSize = mFileSize - mCurrPos;
buf = new char[bufSize];
}
ifs.read(buf, bufSize);
mSocket->send(buffer(buf, bufSize));
mCurrPos += bufSize;
std::cout << "CLIENT " << mCurrPos << std::endl;
}
ifs.close();
delete[] buf;
mWorkerOccupied = false;
slDebug("SendFile completed");
All this stuff is running in parallels threads. From my understanding it should be working this way:
I have a output of current position of file in both client and server loop. I expect it to be something like:
CLIENT 228 // first we send some data
SERVER 228 // Server gets it and outputs the same file pos
or
CLIENT 228
CLIENT 456
SERVER 228
SERVER 456
But what I am actually getting - confuses me...
SERVER 499384320
SERVER 499646464
CLIENT 88604672
SERVER 499908608
CLIENT 88866816
SERVER 500170752
SERVER 500432896
SERVER 500695040
SERVER 500957184
Far more messages regarding receiving something by server, than client ones about sending. How it can be? Literally, looks like client sent only 80mb of data, while server already received 500mb of data... I thought, that server thread should wait on receive(), since I am using blocking socket, but this is strange. Could someone explain me, why I have this huge desync?
You're assuming that receive
reads the entire buffer size at once, but it doesn't necessarily:
The receive operation may not receive all of the requested number of bytes. Consider using
the read function if you need to ensure that the requested amount of data is read before the
blocking operation completes
receive
returns the amount of data read, you should change your code to something like:
size_t recvd = mSocket->receive(buffer(buf, bufSize));
ofs.write(buf, recvd);
currPos += recvd;