Use MSG_WAITALL
This commit is contained in:
parent
3a528ad2cc
commit
b3b3ee9d49
|
@ -7,119 +7,65 @@ public bool receiveMessage(Socket originator, ref byte[] receiveMessage)
|
|||
/* Construct a buffer to receive into */
|
||||
byte[] receiveBuffer;
|
||||
|
||||
/* The current byte */
|
||||
uint currentByte = 0;
|
||||
bool status = true;
|
||||
|
||||
|
||||
/* The amount of bytes received */
|
||||
long bytesReceived;
|
||||
|
||||
/* Loop consume the next 4 bytes */
|
||||
while(currentByte < 4)
|
||||
{
|
||||
/* Temporary buffer */
|
||||
byte[4] tempBuffer;
|
||||
/* Get the length of the message */
|
||||
byte[4] messageLengthBytes;
|
||||
bytesReceived = originator.receive(messageLengthBytes, cast(SocketFlags)MSG_WAITALL);
|
||||
|
||||
/* Read at-most 4 bytes */
|
||||
bytesReceived = originator.receive(tempBuffer);
|
||||
/* If there was an error reading from the socket */
|
||||
if(!(bytesReceived > 0))
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
/* If the receive was successful */
|
||||
else
|
||||
{
|
||||
/* Response message length */
|
||||
uint messageLength;
|
||||
|
||||
/* Little endian version you simply read if off the bone (it's already in the correct order) */
|
||||
version(LittleEndian)
|
||||
{
|
||||
messageLength = *cast(int*)messageLengthBytes.ptr;
|
||||
}
|
||||
|
||||
/* Big endian requires we byte-sapped the little-endian encoded number */
|
||||
version(BigEndian)
|
||||
{
|
||||
byte[] swappedLength;
|
||||
swappedLength.length = 4;
|
||||
|
||||
swappedLength[0] = messageLengthBytes[3];
|
||||
swappedLength[1] = messageLengthBytes[2];
|
||||
swappedLength[2] = messageLengthBytes[1];
|
||||
swappedLength[3] = messageLengthBytes[0];
|
||||
|
||||
messageLength = *cast(int*)swappedLength.ptr;
|
||||
}
|
||||
|
||||
|
||||
/* Read the full message */
|
||||
receiveBuffer.length = messageLength;
|
||||
bytesReceived = originator.receive(receiveBuffer, cast(SocketFlags)MSG_WAITALL);
|
||||
|
||||
/* If there was an error reading from the socket */
|
||||
if(!(bytesReceived > 0))
|
||||
{
|
||||
return false;
|
||||
status = false;
|
||||
}
|
||||
/* If there is no error reading from the socket */
|
||||
/* If there was no error receiving the message */
|
||||
else
|
||||
{
|
||||
/* Add the read bytes to the *real* buffer */
|
||||
receiveBuffer ~= tempBuffer[0..bytesReceived];
|
||||
|
||||
/* Increment the byte counter */
|
||||
currentByte += bytesReceived;
|
||||
receiveMessage = receiveBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Response message length */
|
||||
int messageLength;
|
||||
|
||||
/* Little endian version you simply read if off the bone (it's already in the correct order) */
|
||||
version(LittleEndian)
|
||||
{
|
||||
messageLength = *cast(int*)receiveBuffer.ptr;
|
||||
}
|
||||
|
||||
/* Big endian requires we byte-sapped the little-endian encoded number */
|
||||
version(BigEndian)
|
||||
{
|
||||
byte[] swappedLength;
|
||||
swappedLength.length = 4;
|
||||
|
||||
swappedLength[0] = receiveBuffer[3];
|
||||
swappedLength[1] = receiveBuffer[2];
|
||||
swappedLength[2] = receiveBuffer[1];
|
||||
swappedLength[3] = receiveBuffer[0];
|
||||
|
||||
messageLength = *cast(int*)swappedLength.ptr;
|
||||
}
|
||||
|
||||
/* Full message buffer Reset buffer */
|
||||
byte[] fullMessage;
|
||||
|
||||
/* Reset the byte counter */
|
||||
currentByte = 0;
|
||||
|
||||
while(currentByte < messageLength)
|
||||
{
|
||||
/**
|
||||
* Receive 20 bytes (at most) at a time and don't dequeue from
|
||||
* the kernel's TCP stack's buffer.
|
||||
*/
|
||||
byte[20] tempBuffer;
|
||||
bytesReceived = originator.receive(tempBuffer, SocketFlags.PEEK);
|
||||
|
||||
/* Check for an error whilst receiving */
|
||||
if(!(bytesReceived > 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cast(uint)bytesReceived+currentByte > messageLength)
|
||||
{
|
||||
byte[] remainingBytes;
|
||||
remainingBytes.length = messageLength-currentByte;
|
||||
|
||||
/* Receive the remaining bytes */
|
||||
originator.receive(remainingBytes);
|
||||
|
||||
/* Increment counter of received bytes */
|
||||
currentByte += remainingBytes.length;
|
||||
|
||||
/* Append the received bytes to the FULL message buffer */
|
||||
fullMessage ~= remainingBytes;
|
||||
|
||||
// writeln("Received ", currentByte, "/", cast(uint)messageLength, " bytes");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increment counter of received bytes */
|
||||
currentByte += bytesReceived;
|
||||
|
||||
/* Append the received bytes to the FULL message buffer */
|
||||
fullMessage ~= tempBuffer[0..bytesReceived];
|
||||
|
||||
/* TODO: Bug when over send, we must not allow this */
|
||||
// writeln("Received ", currentByte, "/", cast(uint)messageLength, " bytes");
|
||||
|
||||
/* Dequeue the received bytes */
|
||||
originator.receive(tempBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the message in `receiveMessage */
|
||||
receiveMessage = fullMessage;
|
||||
|
||||
return true;
|
||||
return status;
|
||||
}
|
||||
|
||||
public bool sendMessage(Socket recipient, byte[] message)
|
||||
|
|
Loading…
Reference in New Issue