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;
397 void 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;
bool operator<(const SocketUDP &Other) const
Comparison operator <.
bool Close()
Close the socket.
static Socket::Status GetErrorStatus()
Get the last socket error status.
SocketUDP wraps a socket using UDP protocol to send data fastly (but with less safety) ...
Packet wraps data to send / to receive through the network.
unsigned short GetPort() const
Get the port the socket is currently bound to.
static SocketType InvalidSocket()
Return the value of the invalid socket.
bool IsValid() const
Check if the socket is in a valid state ; this function can be called any time to check if the socket...
std::string ToString() const
Get a string representation of the address.
void Clear()
Clear the packet data.
bool operator==(const SocketUDP &Other) const
Comparison operator ==.
bool Bind(unsigned short Port)
Bind the socket to a specific port.
IPAddress provides easy manipulation of IP v4 addresses.
bool Unbind()
Unbind the socket from its previous port, if any.
static void SetBlocking(SocketType Socket, bool Block)
Set a socket as blocking or non-blocking.
Socket::Status Receive(char *Data, std::size_t MaxSize, std::size_t &SizeReceived, IPAddress &Address, unsigned short &Port)
Receive an array of bytes.
Socket::Status Send(const char *Data, std::size_t Size, const IPAddress &Address, unsigned short Port)
Send an array of bytes.
void SetBlocking(bool Blocking)
Change the blocking state of the socket.
static bool Close(SocketType Socket)
Close / destroy a socket.
SocketUDP()
Default constructor.
bool operator!=(const SocketUDP &Other) const
Comparison operator !=.