Stream sockets
A stream socket is an endpoint for a reliable point to point communication. The following example code shows, how to establish a stream socket connection.
// server code StreamSocket socket,client; socket.open(); socket.bind(SocketAddress(SocketAddress::ANY,12345)); client=socket.accept(); client.send(buffer,100); client.close(); socket.close();
// client code
StreamSocket server;
server.open();
server.connect(SocketAddress("localhost",12345));
server.recv(buffer,100);
server.close();
The method bind() assigns the socket to a given port and network device. If the network device is ANY, then the socket will accept connections from all network interfaces. If the port number is zero, then a free port is assigned. In the above example, the socket will accept incoming connections at each interface on the port 12345. StreamSocket::accept() waits for a incoming connection. For each incoming connection a new socket object will be created. With send and recv data can be transferred over the connection. By default all calls will block until the operation has finished.
Datagram sockets
Datagram sockets are not connection orientated. There is no connect or accept methods for datagram sockets. You have to provide a destination address for each send and will get a source address for each recv call. There is no guarantee that packages will arrive and there is no guarantee for the order in which the package will arrive. The followin code shows how to wait for incoming packages at port 22222.
SocketAddress client; DgramSocket socket; socket.open(); socket.bind(SocketAddress(SocketAddress::ANY,22222)) socket.recvFrom(buffer,100,client); socket.close();
This is the code to send the package. This is a simple example. If the package gets lost for example because the server is not started, then this code wont work. If your application relays on reliable data transmission, then StreamSockets should be used.
DgramSocket sock;
SocketAddress server;
socket.open();
socket.sendTo("hallo",100,SocketAddress("localhost",22222));
socket.close();
Exceptions:
All socket methods will throw exceptions if the desired function could not be finished. All socket related exceptions are derived from the SocketException class. All socket calls should be enclosed in try/catch blocks. For example, if you want to check if a connect operation was successful then you should use the following code.
try
{
server..connect(SocketAddress("localhost",12345));
}
catch(SocketException &e)
{
SFATAL << "Unable to connect to server:" << e.what() << endl;
}
Each exceptions contains the system error text that causes the error situation. This text can be accessed by SocketException::what(). The text is given as an std:string object.
Broadcast Messages
Broadcast packages are a special case of datagram packages. Broadcast packages are send to each host in a network. For broadcasting packages a special address type is used. For example with the address SocketAddress(SocketAddress::BROADCAST,2345) packages will be send to each host on port number 2345. Equal to normal datagram sockets, broadcast packages are transmitted not reliable.
Multicast Messages
With multicast it is possible to send packages to more then one destination. In contrast to broadcast the package is not send to all hosts but only to those hosts that have joined a multicast group. A multicast group is specified with special IP addresses (224.xxx.xxx.xxx). To write a package to the multicast group 224.22.33.33 at port 4444 you could use
socket.sendTo(buffer,100,SocketAddress("224.22.33.44",4444)
The receive has to join this group. The following examples shows how to join and leave multicast groups. It is possible to join more then one group.
socket.bind(SocketAddress(SocketAddress::ANY,4444));
socket.join(SocketAddress("224.22.33.44"));
socket.join(SocketAddress("224.0.0.52"));
socket.join(SocketAddress("224.0.0.53"));
socket.leave(SocketAddress("224.0.0.52"));
With multicast groups you also have to bind your socket to a network device and port. In the example above only those packages are received that are send to port 4444. With multicast it often happens, that you have more then one member of a multicast group on a single host. If you try to call bind for the same port multiple times, then you will get socket exceptions. To be able to assign more then one process to the same port you have to call socket.setReusePort(true) before the call to bind.
It is possible set the network device that is used to send multicast packages. By default the system uses the first device that is capable to send multicast packages.
socket.setInterface(SocketAddress("192.168.10.1"));
Nonblocking IO
In many applications it is not possible or not wanted to block execution until an accept() or recv() call has finished. Each socket has methods to ask if it is possible to read or write data without blocking. The followin examples shows how to wait for data without blocking.
With this simple interface it is possible to wait a specified time for incoming or outgoing data. But it is only possible to wait for exactly one socket. If it is necessary to wait for more then one socket then the Selection class could be used. A selection specifies for each socket for what kind of event the system should wait.
SocketSelection s; s.setRead(socket1); s.setRead(socket2); s.select(.1); if(s.isSetRead(sock1)) socket 1 is readable if(s.isSetRead(sock2)) socket 1 is readable
A call of selection.select(seconds) waits the given number of seconds for the events set with setRead() or serWrite(). It returns after the first occurrence of an event. If no events occur in the given periode then 0 is returned. Otherwise the number of readable and writable sockets is returned. The method select() modifies the selection object. You have to call setRead() and setWrite() for each time, you want to call select(). If the SocketSelection is constant, then you can use an other version of select. With s.select(seconds,rs) s will not be modified. The result will be set into the SocketSelection rs. You have to call rs.isReadable(sock) instead of s.isReadable(sock).
IO-Buffers
If data should be read from more then one socket, then the performance could be improved by not reading from the first socket that provides data but from that socket with the most data in the input buffer. With socket.getAvailable() the number of bytes in the input buffer could be retrieved. In addition the Socket class provides the functions setWriteBufferSize and setReadBufferSize set the size of input and output buffers. Current sizes can be retrieved with getReadBufferSize and getWriteBufferSize.
1.5.5