Sockets can now handle properly the situation where the packet size is received in multiple chunks
git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/trunk@1433 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
parent
4a840d4f48
commit
786408c5bc
@ -214,8 +214,10 @@ private :
|
|||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SocketHelper::SocketType mySocket; ///< Socket descriptor
|
SocketHelper::SocketType mySocket; ///< Socket descriptor
|
||||||
std::vector<char> myPendingPacket; ///< Data of the current pending packet, if any (in non-blocking mode)
|
Uint32 myPendingHeader; ///< Data of the current pending packet header, if any
|
||||||
Int32 myPendingPacketSize; ///< Size of the current pending packet, if any (in non-blocking mode)
|
Uint32 myPendingHeaderSize; ///< Size of the current pending packet header, if any
|
||||||
|
std::vector<char> myPendingPacket; ///< Data of the current pending packet, if any
|
||||||
|
Int32 myPendingPacketSize; ///< Size of the current pending packet, if any
|
||||||
bool myIsBlocking; ///< Is the socket blocking or non-blocking ?
|
bool myIsBlocking; ///< Is the socket blocking or non-blocking ?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,8 +215,10 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SocketHelper::SocketType mySocket; ///< Socket identifier
|
SocketHelper::SocketType mySocket; ///< Socket identifier
|
||||||
unsigned short myPort; ///< Port to which the socket is bound
|
unsigned short myPort; ///< Port to which the socket is bound
|
||||||
std::vector<char> myPendingPacket; ///< Data of the current pending packet, if any (in non-blocking mode)
|
Uint32 myPendingHeader; ///< Data of the current pending packet header, if any
|
||||||
Int32 myPendingPacketSize; ///< Size of the current pending packet, if any (in non-blocking mode)
|
Uint32 myPendingHeaderSize; ///< Size of the current pending packet header, if any
|
||||||
|
std::vector<char> myPendingPacket; ///< Data of the current pending packet, if any
|
||||||
|
Int32 myPendingPacketSize; ///< Size of the current pending packet, if any
|
||||||
bool myIsBlocking; ///< Is the socket blocking or non-blocking ?
|
bool myIsBlocking; ///< Is the socket blocking or non-blocking ?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -344,11 +344,20 @@ Socket::Status SocketTCP::Receive(Packet& PacketToReceive)
|
|||||||
std::size_t Received = 0;
|
std::size_t Received = 0;
|
||||||
if (myPendingPacketSize < 0)
|
if (myPendingPacketSize < 0)
|
||||||
{
|
{
|
||||||
Socket::Status Status = Receive(reinterpret_cast<char*>(&PacketSize), sizeof(PacketSize), Received);
|
// Loop until we've received the entire size of the packet
|
||||||
if (Status != Socket::Done)
|
// (even a 4 bytes variable may be received in more than one call)
|
||||||
return Status;
|
while (myPendingHeaderSize < sizeof(myPendingHeader))
|
||||||
|
{
|
||||||
|
char* Data = reinterpret_cast<char*>(&myPendingHeader) + myPendingHeaderSize;
|
||||||
|
Socket::Status Status = Receive(Data, sizeof(myPendingHeader) - myPendingHeaderSize, Received);
|
||||||
|
myPendingHeaderSize += Received;
|
||||||
|
|
||||||
PacketSize = ntohl(PacketSize);
|
if (Status != Socket::Done)
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketSize = ntohl(myPendingHeader);
|
||||||
|
myPendingHeaderSize = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -472,6 +481,7 @@ void SocketTCP::Create(SocketHelper::SocketType Descriptor)
|
|||||||
myIsBlocking = true;
|
myIsBlocking = true;
|
||||||
|
|
||||||
// Reset the pending packet
|
// Reset the pending packet
|
||||||
|
myPendingHeaderSize = 0;
|
||||||
myPendingPacket.clear();
|
myPendingPacket.clear();
|
||||||
myPendingPacketSize = -1;
|
myPendingPacketSize = -1;
|
||||||
|
|
||||||
|
@ -244,20 +244,25 @@ Socket::Status SocketUDP::Send(Packet& PacketToSend, const IPAddress& Address, u
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Socket::Status SocketUDP::Receive(Packet& PacketToReceive, IPAddress& Address, unsigned short& Port)
|
Socket::Status SocketUDP::Receive(Packet& PacketToReceive, IPAddress& Address, unsigned short& Port)
|
||||||
{
|
{
|
||||||
// This is not safe at all, as data can be lost, duplicated, or arrive in a different order.
|
|
||||||
// So if a packet is split into more than one chunk, nobody knows what could happen...
|
|
||||||
// Conclusion : we shouldn't use packets with UDP, unless we build a more complex protocol on top of it.
|
|
||||||
|
|
||||||
// We start by getting the size of the incoming packet
|
// We start by getting the size of the incoming packet
|
||||||
Uint32 PacketSize = 0;
|
Uint32 PacketSize = 0;
|
||||||
std::size_t Received = 0;
|
std::size_t Received = 0;
|
||||||
if (myPendingPacketSize < 0)
|
if (myPendingPacketSize < 0)
|
||||||
{
|
{
|
||||||
Socket::Status Status = Receive(reinterpret_cast<char*>(&PacketSize), sizeof(PacketSize), Received, Address, Port);
|
// Loop until we've received the entire size of the packet
|
||||||
if (Status != Socket::Done)
|
// (even a 4 bytes variable may be received in more than one call)
|
||||||
return Status;
|
while (myPendingHeaderSize < sizeof(myPendingHeader))
|
||||||
|
{
|
||||||
|
char* Data = reinterpret_cast<char*>(&myPendingHeader) + myPendingHeaderSize;
|
||||||
|
Socket::Status Status = Receive(Data, sizeof(myPendingHeader) - myPendingHeaderSize, Received, Address, Port);
|
||||||
|
myPendingHeaderSize += Received;
|
||||||
|
|
||||||
PacketSize = ntohl(PacketSize);
|
if (Status != Socket::Done)
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketSize = ntohl(myPendingHeader);
|
||||||
|
myPendingHeaderSize = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -265,9 +270,6 @@ Socket::Status SocketUDP::Receive(Packet& PacketToReceive, IPAddress& Address, u
|
|||||||
PacketSize = myPendingPacketSize;
|
PacketSize = myPendingPacketSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the user packet
|
|
||||||
PacketToReceive.Clear();
|
|
||||||
|
|
||||||
// Use another address instance for receiving the packet data ;
|
// Use another address instance for receiving the packet data ;
|
||||||
// chunks of data coming from a different sender will be discarded (and lost...)
|
// chunks of data coming from a different sender will be discarded (and lost...)
|
||||||
IPAddress Sender;
|
IPAddress Sender;
|
||||||
@ -402,6 +404,7 @@ void SocketUDP::Create(SocketHelper::SocketType Descriptor)
|
|||||||
myPort = 0;
|
myPort = 0;
|
||||||
|
|
||||||
// Reset the pending packet
|
// Reset the pending packet
|
||||||
|
myPendingHeaderSize = 0;
|
||||||
myPendingPacket.clear();
|
myPendingPacket.clear();
|
||||||
myPendingPacketSize = -1;
|
myPendingPacketSize = -1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user