Fixed TCP packet data corruption in non-blocking mode (#402, #119)

This commit is contained in:
Laurent Gomila 2013-06-17 18:47:16 +02:00
parent 94fc605a70
commit 4d78d02b5c

View File

@ -282,27 +282,28 @@ Socket::Status TcpSocket::send(Packet& packet)
// This means that we have to send the packet size first, so that the // This means that we have to send the packet size first, so that the
// receiver knows the actual end of the packet in the data stream. // receiver knows the actual end of the packet in the data stream.
// We allocate an extra memory block so that the size can be sent
// together with the data in a single call. This may seem inefficient,
// but it is actually required to avoid partial send, which could cause
// data corruption on the receiving end.
// Get the data to send from the packet // Get the data to send from the packet
std::size_t size = 0; std::size_t size = 0;
const void* data = packet.onSend(size); const void* data = packet.onSend(size);
// First send the packet size // First convert the packet size to network byte order
Uint32 packetSize = htonl(static_cast<Uint32>(size)); Uint32 packetSize = htonl(static_cast<Uint32>(size));
Status status = send(reinterpret_cast<const char*>(&packetSize), sizeof(packetSize));
// Make sure that the size was properly sent // Allocate memory for the data block to send
if (status != Done) std::vector<char> blockToSend(sizeof(packetSize) + size);
return status;
// Send the packet data // Copy the packet size and data into the block to send
if (packetSize > 0) std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
{ if (size > 0)
return send(data, size); std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
}
else // Send the data block
{ return send(&blockToSend[0], blockToSend.size());
return Done;
}
} }