Unigine::Socket Class
Header: | #include <UnigineStreams.h> |
Inherits from: | Stream |
This class provides basic functionality for network interaction using stream sockets.
Usage Example#
In this example we create UDP sockets: server and five clients.
- The server sends broadcast packets containing the ID of the receiving client.
- Each client processes only the messages, that were addressed to it.
- In the world's update() method the server sends messages addressed to clients 2 and 5.
In the AppWorldLogic.h header file we describe our client and server and declare server and array of clients.
#ifndef __APP_WORLD_LOGIC_H__
#define __APP_WORLD_LOGIC_H__
#include <UnigineLogic.h>
#include <UnigineStreams.h>
// UDP port to be used
const int UDP_PORT = 8889;
// UDP receive buffer size
const int RECV_SIZE = 7;
// UDP send buffer size
const int SEND_SIZE = 7;
/* ... */
/// Class representing the Server Socket
class ServerSocket
{
public:
/// Server constructor
ServerSocket()
{
// creating a UDP socket
socket = Unigine::Socket::create(Unigine::Socket::SOCKET_TYPE_DGRAM);
// opening a socket on the specified port with a specified broadcast address
socket->open("127.255.255.255", UDP_PORT);
// setting the size of the sending buffer
socket->send(SEND_SIZE);
// setting the socket as a broadcasting one
socket->broadcast();
// setting the socket as a non-blocking one
socket->nonblock();
}
/// Server destructor
~ServerSocket()
{
// closing the socket
socket->close();
// destroying the socket
socket.deleteLater();
}
/// method sending a message to a certain client
void send_message(int client_num, const char* message)
{
// preparing a message to be received by a client with a given client_id
Unigine::BlobPtr blob = Unigine::Blob::create();
blob->clear();
blob->writeShort(client_num);
blob->write(message, strlen(message));
int size = blob->getSize();
// sending the message
socket->write(blob->getData(), size);
blob.clear();
}
private:
// socket pointer
Unigine::SocketPtr socket;
};
/// Class representing the Client Socket
class ClientSocket {
public:
/// Client constructor
ClientSocket()
{
// creating a UDP socket
socket = Unigine::Socket::create(Unigine::Socket::SOCKET_TYPE_DGRAM);
// opening a socket on the specified port
socket->open(UDP_PORT);
// setting the size of the receiving buffer
socket->recv(RECV_SIZE);
// binding the socket to an address figured out from the host used for socket initialization
socket->bind();
// setting the socket as a non-blocking one
socket->nonblock();
}
/// Client destructor
~ClientSocket()
{
// closing the socket
socket->close();
// destroying the socket
socket.deleteLater();
}
void setID(int num)
{
// setting client's ID
id = num;
}
/// method checking for received packes from the server
int update()
{
// preparing a blob to read the message into
Unigine::BlobPtr temp_blob = Unigine::Blob::create();
temp_blob->clear();
// reading data from the socket
socket->readStream(temp_blob, RECV_SIZE);
if (temp_blob->getSize() > 0) {
// setting current position to start
temp_blob->seekSet(0);
// getting client's ID
int num_client = temp_blob->readShort();
// checking if the received message is addressed to this particular client and processing it
if (num_client == id) {
Unigine::Log::message("\nClient[%d] - OPERATION_CODE: %s", id, temp_blob->readLine().get());
}
}
return 1;
}
private:
// socket pointer
Unigine::SocketPtr socket;
// client ID
int id = 0;
};
class AppWorldLogic : public Unigine::WorldLogic
{
public:
AppWorldLogic();
virtual ~AppWorldLogic();
int init() override;
int update() override;
int postUpdate() override;
int updatePhysics() override;
int shutdown() override;
int save(const Unigine::StreamPtr &stream) override;
int restore(const Unigine::StreamPtr &stream) override;
private:
// declaring client and server sockets
ServerSocket server_socket;
ClientSocket clients[5];
};
#endif // __APP_WORLD_LOGIC_H__
In the AppWorldLogic.cpp implementation file we do the following:
- In the AppWorldLogic::init() method we initialize our clients.
- In the AppWorldLogic::update() we check which keys were pressed and send messages to corresponding clients:
- Client 2 - on ENTER key
- Client 5 - on WASD keys
Here are the AppWorldLogic::init() and AppWorldLogic::update() methods:
// AppWorldLogic.cpp
#include <UnigineControls.h>
#include <UnigineGame.h>
using namespace Unigine;
/* ... */
int AppWorldLogic::init()
{
//initializing clients IDs
for (int i = 0; i < 5; i++)
clients[i].setID(i+1);
return 1;
}
int AppWorldLogic::update()
{
// getting player's controls
ControlsPtr controls = Game::getPlayer()->getControls();
// sending messages on keys pressed to clients 2 and 5
if (controls->clearState(Controls::STATE_USE))
server_socket.send_message(2, "SWT");
else if (controls->clearState(Controls::STATE_FORWARD))
server_socket.send_message(5, "F");
else if (controls->clearState(Controls::STATE_BACKWARD))
server_socket.send_message(5, "B");
else if (controls->clearState(Controls::STATE_MOVE_LEFT))
server_socket.send_message(5, "L");
else if (controls->clearState(Controls::STATE_MOVE_RIGHT))
server_socket.send_message(5, "R");
// updating clients
for (int i = 0; i < 5; i++)
clients[i].update();
return 1;
}
/* ... */
See Also#
A set of UnigineScript API samples located in the <UnigineSDK>/data/samples/systems/ folder:
- socket_00
- socket_01
- socket_02
- socket_03
- socket_04
Socket Class
Enums
SOCKET_TYPE#
Name | Description |
---|---|
SOCKET_TYPE_STREAM = 0 | Socket for TCP packets. |
SOCKET_TYPE_DGRAM = 1 | Socket for UDP packets. |
Members
static SocketPtr create ( Socket::SOCKET_TYPE type ) #
Creates a socket of the specified type. When the socket receives data, packets from all network interfaces will be received. When the socket sends data, the default IP address will be used.Arguments
- Socket::SOCKET_TYPE type - Socket type for TCP or UDP connections.
static SocketPtr create ( Socket::SOCKET_TYPE type, int port ) #
Creates a socket for TCP or UDP connections and opens it on a given port. When the socket receives data, packets from all network interfaces will be received. When the socket sends data, the default IP address will be used.Arguments
- Socket::SOCKET_TYPE type - Socket type for TCP or UDP connections.
- int port - Port, on which the socket will be opened.
static SocketPtr create ( Socket::SOCKET_TYPE type, const char * host, int port ) #
Creates a socket for TCP or UDP connections and opens it on a given host and a given port. The host specifies the address, from and to which data will be sent.Arguments
- Socket::SOCKET_TYPE type - Socket type for TCP or UDP connections.
- const char * host - Host, on which the socket will be opened.
- int port - Port, on which the socket will be opened.
int getFD ( ) const#
Returns the socket file descriptor.Return value
Socket file descriptor.const char * getHost ( ) const#
Returns the host name on which the socket is opened.Return value
Host name.int getPort ( ) const#
Returns the port number on which the socket is opened.Return value
Port number.bool accept ( const Ptr<Socket> & socket ) #
Accepts a connection on the socket.Arguments
- const Ptr<Socket> & socket - Socket that is bound to an address and listens to connections.
Return value
1 if the connection is accepted; otherwise, 0.bool bind ( ) #
Binds the socket to an address figured out from the host used for socket initialization.Return value
true if the address is bound; otherwise, false.bool block ( ) #
Sets up a blocking socket.Return value
true if the socket is opened; otherwise, false.bool broadcast ( ) #
Sets up a broadcast socket. To create a broadcast socket, you need to create it with a broadcast host address first and then use this function.Return value
true if the socket is set up successfully; otherwise, false is returned.void close ( ) #
Closes the socket.bool connect ( ) #
Initiates a connection on the socket.Return value
true if the connection is initialized; otherwise, false.bool listen ( int num ) #
Makes the socket listen to connections.Arguments
- int num - Maximum number of pending connections.
Return value
true if the socket has started listening; otherwise, false.bool listenMulticastGroup ( ) #
Joins the socket to a multicast group. Available for UDP sockets only.The socket class doesn't allow creating a multicast server.
const int PORT = 8888;
SocketPtr socket = Socket::create(Socket::SOCKET_TYPE_DGRAM, PORT);
socket->listenMulticastGroup();
Return value
true if the sockect has been joined successfully; otherwise, false.bool nodelay ( ) #
Enables Nagle's algorithm.Return value
true if the algorithm has been enabled successfully; otherwise, false.bool nonblock ( ) #
Makes the socket a non-blocking one.Return value
true if the has become non-blocking; otherwise, false.bool open ( int port ) #
Opens the socket on a given port. When the socket receives data, packets from all network interfaces will be received. When the socket sends data, the default IP address will be used.Arguments
- int port - Port number, on which the socket will be opened.
Return value
true if the socket is opened successfully; otherwise, false.bool open ( const char * host, int port ) #
Opens the socket on a given port. When the socket receives data, packets from all network interfaces will be received. When the socket sends data, the default IP address will be used.Arguments
- const char * host - Host name, on which the socket will be opened.
- int port - Port number, on which the socket will be opened.
Return value
true if the socket is opened successfully; otherwise, false.bool recv ( int size ) #
Resizes an internal receiving buffer for a socket.Arguments
- int size - Receive buffer size in bytes.
Return value
true if the buffer is resized successfully; otherwise, false.bool send ( int size ) #
Resizes an internal sending buffer for a socket.Arguments
- int size - Send buffer size in bytes.
Return value
true if the buffer is resized successfully; otherwise, false.bool isReadyToRead ( int timeout_usec = 0 ) const#
Returns a value indicating whether the socked is ready for reading data, waiting if necessary, to perform synchronous I/O.Arguments
- int timeout_usec - The maximum time for to wait for the socket's response, in microseconds. By default, the timeout is 0
Return value
true if the socket is ready for reading data; otherwise, false.bool isReadyToWrite ( int timeout_usec = 0 ) const#
Returns a value indicating whether the socked is ready for writing data, waiting if necessary, to perform synchronous I/O.Arguments
- int timeout_usec - The maximum time for to wait for the socket's response, in microseconds. By default, the timeout is 0
Return value
true if the socket is ready for writing data; otherwise, false.Last update:
2024-12-13
Help improve this article
Was this article helpful?
(or select a word/phrase and press Ctrl+Enter)