28#include <SFML/Network/SocketUDP.hpp>
29#include <SFML/Network/IPAddress.hpp>
30#include <SFML/Network/Packet.hpp>
57 myIsBlocking = Blocking;
76 Addr.sin_family = AF_INET;
77 Addr.sin_port = htons(Port);
78 Addr.sin_addr.s_addr = INADDR_ANY;
79 memset(Addr.sin_zero, 0,
sizeof(Addr.sin_zero));
82 if (bind(mySocket,
reinterpret_cast<sockaddr*
>(&Addr),
sizeof(Addr)) == -1)
84 std::cerr <<
"Failed to bind the socket to port " << Port << std::endl;
129 Target.sin_family = AF_INET;
130 Target.sin_port = htons(Port);
131 Target.sin_addr.s_addr = inet_addr(Address.
ToString().c_str());
132 memset(Target.sin_zero, 0,
sizeof(Target.sin_zero));
136 int SizeToSend =
static_cast<int>(Size);
137 for (
int Length = 0; Length < SizeToSend; Length += Sent)
140 Sent = sendto(mySocket, Data + Length, SizeToSend - Length, 0,
reinterpret_cast<sockaddr*
>(&Target),
sizeof(Target));
152 std::cerr <<
"Cannot send data over the network (invalid parameters)" << std::endl;
153 return Socket::Error;
170 std::cerr <<
"Failed to receive data ; the UDP socket first needs to be bound to a port" << std::endl;
171 return Socket::Error;
183 Sender.sin_family = AF_INET;
185 Sender.sin_addr.s_addr = INADDR_ANY;
186 memset(Sender.sin_zero, 0,
sizeof(Sender.sin_zero));
187 SocketHelper::LengthType SenderSize =
sizeof(Sender);
190 int Received = recvfrom(mySocket, Data,
static_cast<int>(MaxSize), 0,
reinterpret_cast<sockaddr*
>(&Sender), &SenderSize);
195 Address =
IPAddress(inet_ntoa(Sender.sin_addr));
196 Port = ntohs(Sender.sin_port);
197 SizeReceived =
static_cast<std::size_t
>(Received);
210 std::cerr <<
"Cannot receive data from the network (invalid parameters)" << std::endl;
211 return Socket::Error;
222 std::size_t DataSize = 0;
223 const char* Data = PacketToSend.OnSend(DataSize);
226 Uint32 PacketSize = htonl(
static_cast<unsigned long>(DataSize));
227 Send(
reinterpret_cast<const char*
>(&PacketSize),
sizeof(PacketSize), Address, Port);
232 return Send(Data, DataSize, Address, Port);
248 Uint32 PacketSize = 0;
249 std::size_t Received = 0;
250 if (myPendingPacketSize < 0)
254 while (myPendingHeaderSize <
sizeof(myPendingHeader))
256 char* Data =
reinterpret_cast<char*
>(&myPendingHeader) + myPendingHeaderSize;
257 Socket::Status Status =
Receive(Data,
sizeof(myPendingHeader) - myPendingHeaderSize, Received, Address, Port);
258 myPendingHeaderSize += Received;
260 if (Status != Socket::Done)
264 PacketSize = ntohl(myPendingHeader);
265 myPendingHeaderSize = 0;
270 PacketSize = myPendingPacketSize;
276 unsigned short SenderPort;
280 while (myPendingPacket.size() < PacketSize)
283 std::size_t SizeToGet = std::min(
static_cast<std::size_t
>(PacketSize - myPendingPacket.size()),
sizeof(Buffer));
284 Socket::Status Status =
Receive(Buffer, SizeToGet, Received, Sender, SenderPort);
285 if (Status != Socket::Done)
288 if (Status == Socket::NotReady)
289 myPendingPacketSize = PacketSize;
294 if ((Sender == Address) && (SenderPort == Port) && (Received > 0))
296 myPendingPacket.resize(myPendingPacket.size() + Received);
297 char* Begin = &myPendingPacket[0] + myPendingPacket.size() - Received;
298 memcpy(Begin, Buffer, Received);
303 PacketToReceive.
Clear();
304 if (!myPendingPacket.empty())
305 PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size());
306 myPendingPacket.clear();
307 myPendingPacketSize = -1;
322 std::cerr <<
"Failed to close socket" << std::endl;
360 return mySocket == Other.mySocket;
369 return mySocket != Other.mySocket;
380 return mySocket < Other.mySocket;
397void SocketUDP::Create(SocketHelper::SocketType Descriptor)
400 mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_DGRAM, 0);
407 myPendingHeaderSize = 0;
408 myPendingPacket.clear();
409 myPendingPacketSize = -1;
416 if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char*
>(&Yes),
sizeof(Yes)) == -1)
418 std::cerr <<
"Failed to set socket option \"reuse address\" ; "
419 <<
"binding to a same port may fail if too fast" << std::endl;
423 if (setsockopt(mySocket, SOL_SOCKET, SO_BROADCAST,
reinterpret_cast<char*
>(&Yes),
sizeof(Yes)) == -1)
425 std::cerr <<
"Failed to enable broadcast on UDP socket" << std::endl;
IPAddress provides easy manipulation of IP v4 addresses.
std::string ToString() const
Get a string representation of the address.
Packet wraps data to send / to receive through the network.
void Clear()
Clear the packet data.
static void SetBlocking(SocketType Socket, bool Block)
Set a socket as blocking or non-blocking.
static Socket::Status GetErrorStatus()
Get the last socket error status.
static SocketType InvalidSocket()
Return the value of the invalid socket.
static bool Close(SocketType Socket)
Close / destroy a socket.
unsigned short GetPort() const
Get the port the socket is currently bound to.
void SetBlocking(bool Blocking)
Change the blocking state of the socket.
bool Bind(unsigned short Port)
Bind the socket to a specific port.
bool Unbind()
Unbind the socket from its previous port, if any.
bool operator==(const SocketUDP &Other) const
Comparison operator ==.
SocketUDP()
Default constructor.
bool IsValid() const
Check if the socket is in a valid state ; this function can be called any time to check if the socket...
Socket::Status Send(const char *Data, std::size_t Size, const IPAddress &Address, unsigned short Port)
Send an array of bytes.
Socket::Status Receive(char *Data, std::size_t MaxSize, std::size_t &SizeReceived, IPAddress &Address, unsigned short &Port)
Receive an array of bytes.
bool Close()
Close the socket.
bool operator<(const SocketUDP &Other) const
Comparison operator <.
bool operator!=(const SocketUDP &Other) const
Comparison operator !=.