292 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			292 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| ////////////////////////////////////////////////////////////
 | |
| //
 | |
| // SFML - Simple and Fast Multimedia Library
 | |
| // Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
 | |
| //
 | |
| // This software is provided 'as-is', without any express or implied warranty.
 | |
| // In no event will the authors be held liable for any damages arising from the use of this software.
 | |
| //
 | |
| // Permission is granted to anyone to use this software for any purpose,
 | |
| // including commercial applications, and to alter it and redistribute it freely,
 | |
| // subject to the following restrictions:
 | |
| //
 | |
| // 1. The origin of this software must not be misrepresented;
 | |
| //    you must not claim that you wrote the original software.
 | |
| //    If you use this software in a product, an acknowledgment
 | |
| //    in the product documentation would be appreciated but is not required.
 | |
| //
 | |
| // 2. Altered source versions must be plainly marked as such,
 | |
| //    and must not be misrepresented as being the original software.
 | |
| //
 | |
| // 3. This notice may not be removed or altered from any source distribution.
 | |
| //
 | |
| ////////////////////////////////////////////////////////////
 | |
| 
 | |
| #ifndef SFML_UDPSOCKET_HPP
 | |
| #define SFML_UDPSOCKET_HPP
 | |
| 
 | |
| ////////////////////////////////////////////////////////////
 | |
| // Headers
 | |
| ////////////////////////////////////////////////////////////
 | |
| #include <SFML/Network/Export.hpp>
 | |
| #include <SFML/Network/Socket.hpp>
 | |
| #include <SFML/Network/IpAddress.hpp>
 | |
| #include <vector>
 | |
| 
 | |
| 
 | |
| namespace sf
 | |
| {
 | |
| class Packet;
 | |
| 
 | |
| ////////////////////////////////////////////////////////////
 | |
| /// \brief Specialized socket using the UDP protocol
 | |
| ///
 | |
| ////////////////////////////////////////////////////////////
 | |
| class SFML_NETWORK_API UdpSocket : public Socket
 | |
| {
 | |
| public:
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     // Constants
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     enum
 | |
|     {
 | |
|         MaxDatagramSize = 65507 ///< The maximum number of bytes that can be sent in a single UDP datagram
 | |
|     };
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     /// \brief Default constructor
 | |
|     ///
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     UdpSocket();
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     /// \brief Get the port to which the socket is bound locally
 | |
|     ///
 | |
|     /// If the socket is not bound to a port, this function
 | |
|     /// returns 0.
 | |
|     ///
 | |
|     /// \return Port to which the socket is bound
 | |
|     ///
 | |
|     /// \see bind
 | |
|     ///
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     unsigned short getLocalPort() const;
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     /// \brief Bind the socket to a specific port
 | |
|     ///
 | |
|     /// Binding the socket to a port is necessary for being
 | |
|     /// able to receive data on that port.
 | |
|     /// You can use the special value Socket::AnyPort to tell the
 | |
|     /// system to automatically pick an available port, and then
 | |
|     /// call getLocalPort to retrieve the chosen port.
 | |
|     ///
 | |
|     /// Since the socket can only be bound to a single port at
 | |
|     /// any given moment, if it is already bound when this
 | |
|     /// function is called, it will be unbound from the previous
 | |
|     /// port before being bound to the new one.
 | |
|     ///
 | |
|     /// \param port    Port to bind the socket to
 | |
|     /// \param address Address of the interface to bind to
 | |
|     ///
 | |
|     /// \return Status code
 | |
|     ///
 | |
|     /// \see unbind, getLocalPort
 | |
|     ///
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     Status bind(unsigned short port, const IpAddress& address = IpAddress::Any);
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     /// \brief Unbind the socket from the local port to which it is bound
 | |
|     ///
 | |
|     /// The port that the socket was previously bound to is immediately
 | |
|     /// made available to the operating system after this function is called.
 | |
|     /// This means that a subsequent call to bind() will be able to re-bind
 | |
|     /// the port if no other process has done so in the mean time.
 | |
|     /// If the socket is not bound to a port, this function has no effect.
 | |
|     ///
 | |
|     /// \see bind
 | |
|     ///
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     void unbind();
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     /// \brief Send raw data to a remote peer
 | |
|     ///
 | |
|     /// Make sure that \a size is not greater than
 | |
|     /// UdpSocket::MaxDatagramSize, otherwise this function will
 | |
|     /// fail and no data will be sent.
 | |
|     ///
 | |
|     /// \param data          Pointer to the sequence of bytes to send
 | |
|     /// \param size          Number of bytes to send
 | |
|     /// \param remoteAddress Address of the receiver
 | |
|     /// \param remotePort    Port of the receiver to send the data to
 | |
|     ///
 | |
|     /// \return Status code
 | |
|     ///
 | |
|     /// \see receive
 | |
|     ///
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     Status send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort);
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     /// \brief Receive raw data from a remote peer
 | |
|     ///
 | |
|     /// In blocking mode, this function will wait until some
 | |
|     /// bytes are actually received.
 | |
|     /// Be careful to use a buffer which is large enough for
 | |
|     /// the data that you intend to receive, if it is too small
 | |
|     /// then an error will be returned and *all* the data will
 | |
|     /// be lost.
 | |
|     ///
 | |
|     /// \param data          Pointer to the array to fill with the received bytes
 | |
|     /// \param size          Maximum number of bytes that can be received
 | |
|     /// \param received      This variable is filled with the actual number of bytes received
 | |
|     /// \param remoteAddress Address of the peer that sent the data
 | |
|     /// \param remotePort    Port of the peer that sent the data
 | |
|     ///
 | |
|     /// \return Status code
 | |
|     ///
 | |
|     /// \see send
 | |
|     ///
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     Status receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort);
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     /// \brief Send a formatted packet of data to a remote peer
 | |
|     ///
 | |
|     /// Make sure that the packet size is not greater than
 | |
|     /// UdpSocket::MaxDatagramSize, otherwise this function will
 | |
|     /// fail and no data will be sent.
 | |
|     ///
 | |
|     /// \param packet        Packet to send
 | |
|     /// \param remoteAddress Address of the receiver
 | |
|     /// \param remotePort    Port of the receiver to send the data to
 | |
|     ///
 | |
|     /// \return Status code
 | |
|     ///
 | |
|     /// \see receive
 | |
|     ///
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     Status send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort);
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     /// \brief Receive a formatted packet of data from a remote peer
 | |
|     ///
 | |
|     /// In blocking mode, this function will wait until the whole packet
 | |
|     /// has been received.
 | |
|     ///
 | |
|     /// \param packet        Packet to fill with the received data
 | |
|     /// \param remoteAddress Address of the peer that sent the data
 | |
|     /// \param remotePort    Port of the peer that sent the data
 | |
|     ///
 | |
|     /// \return Status code
 | |
|     ///
 | |
|     /// \see send
 | |
|     ///
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     Status receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort);
 | |
| 
 | |
| private:
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     // Member data
 | |
|     ////////////////////////////////////////////////////////////
 | |
|     std::vector<char> m_buffer; ///< Temporary buffer holding the received data in Receive(Packet)
 | |
| };
 | |
| 
 | |
| } // namespace sf
 | |
| 
 | |
| 
 | |
| #endif // SFML_UDPSOCKET_HPP
 | |
| 
 | |
| 
 | |
| ////////////////////////////////////////////////////////////
 | |
| /// \class sf::UdpSocket
 | |
| /// \ingroup network
 | |
| ///
 | |
| /// A UDP socket is a connectionless socket. Instead of
 | |
| /// connecting once to a remote host, like TCP sockets,
 | |
| /// it can send to and receive from any host at any time.
 | |
| ///
 | |
| /// It is a datagram protocol: bounded blocks of data (datagrams)
 | |
| /// are transfered over the network rather than a continuous
 | |
| /// stream of data (TCP). Therefore, one call to send will always
 | |
| /// match one call to receive (if the datagram is not lost),
 | |
| /// with the same data that was sent.
 | |
| ///
 | |
| /// The UDP protocol is lightweight but unreliable. Unreliable
 | |
| /// means that datagrams may be duplicated, be lost or
 | |
| /// arrive reordered. However, if a datagram arrives, its
 | |
| /// data is guaranteed to be valid.
 | |
| ///
 | |
| /// UDP is generally used for real-time communication
 | |
| /// (audio or video streaming, real-time games, etc.) where
 | |
| /// speed is crucial and lost data doesn't matter much.
 | |
| ///
 | |
| /// Sending and receiving data can use either the low-level
 | |
| /// or the high-level functions. The low-level functions
 | |
| /// process a raw sequence of bytes, whereas the high-level
 | |
| /// interface uses packets (see sf::Packet), which are easier
 | |
| /// to use and provide more safety regarding the data that is
 | |
| /// exchanged. You can look at the sf::Packet class to get
 | |
| /// more details about how they work.
 | |
| ///
 | |
| /// It is important to note that UdpSocket is unable to send
 | |
| /// datagrams bigger than MaxDatagramSize. In this case, it
 | |
| /// returns an error and doesn't send anything. This applies
 | |
| /// to both raw data and packets. Indeed, even packets are
 | |
| /// unable to split and recompose data, due to the unreliability
 | |
| /// of the protocol (dropped, mixed or duplicated datagrams may
 | |
| /// lead to a big mess when trying to recompose a packet).
 | |
| ///
 | |
| /// If the socket is bound to a port, it is automatically
 | |
| /// unbound from it when the socket is destroyed. However,
 | |
| /// you can unbind the socket explicitly with the Unbind
 | |
| /// function if necessary, to stop receiving messages or
 | |
| /// make the port available for other sockets.
 | |
| ///
 | |
| /// Usage example:
 | |
| /// \code
 | |
| /// // ----- The client -----
 | |
| ///
 | |
| /// // Create a socket and bind it to the port 55001
 | |
| /// sf::UdpSocket socket;
 | |
| /// socket.bind(55001);
 | |
| ///
 | |
| /// // Send a message to 192.168.1.50 on port 55002
 | |
| /// std::string message = "Hi, I am " + sf::IpAddress::getLocalAddress().toString();
 | |
| /// socket.send(message.c_str(), message.size() + 1, "192.168.1.50", 55002);
 | |
| ///
 | |
| /// // Receive an answer (most likely from 192.168.1.50, but could be anyone else)
 | |
| /// char buffer[1024];
 | |
| /// std::size_t received = 0;
 | |
| /// sf::IpAddress sender;
 | |
| /// unsigned short port;
 | |
| /// socket.receive(buffer, sizeof(buffer), received, sender, port);
 | |
| /// std::cout << sender.ToString() << " said: " << buffer << std::endl;
 | |
| ///
 | |
| /// // ----- The server -----
 | |
| ///
 | |
| /// // Create a socket and bind it to the port 55002
 | |
| /// sf::UdpSocket socket;
 | |
| /// socket.bind(55002);
 | |
| ///
 | |
| /// // Receive a message from anyone
 | |
| /// char buffer[1024];
 | |
| /// std::size_t received = 0;
 | |
| /// sf::IpAddress sender;
 | |
| /// unsigned short port;
 | |
| /// socket.receive(buffer, sizeof(buffer), received, sender, port);
 | |
| /// std::cout << sender.ToString() << " said: " << buffer << std::endl;
 | |
| ///
 | |
| /// // Send an answer
 | |
| /// std::string message = "Welcome " + sender.toString();
 | |
| /// socket.send(message.c_str(), message.size() + 1, sender, port);
 | |
| /// \endcode
 | |
| ///
 | |
| /// \see sf::Socket, sf::TcpSocket, sf::Packet
 | |
| ///
 | |
| ////////////////////////////////////////////////////////////
 |