#include <QBlkSocket.h>
This is a synchronous network socket class capable of providing a TCP connection or UDP packet-based transfers. Synchronous means that unlike most socket implementations there is no posting of messages to notify you of events - instead a much simpler and elegant structure is required of having a unique thread wait on input and it can handle and/or dispatch incoming data.
It is also almost API compatible with Qt's QSocketDevice which is Qt's core socket class. Unlike QSocketDevice, QBlkSocket can only behave in a blocking fashion.
Furthermore, QBlkSocket provides a full IPv6 interface as well as IPv4 facilities. All you need to do is set an IPv6 address in FX:QHostAddress and the rest is taken care of for you.
The send and receive buffer sizes are important. If the send buffer size becomes too full to allow insertion of a writeBlock(), writeBlock() will stall until enough data has been sent. This may take seconds and occasionally minutes. The receive buffer size is also important because it limits the maximum data length you can pass to readBlock() which will never return more than readBufferSize() bytes. On Win32, the default read and write buffer sizes appear to be 8192 bytes which is a little small. On Linux on FreeBSD, they are a much more reasonable 49152 bytes.
To create the server end of a socket, instantiate a QBlkSocket just as type and optionally port (if port is zero, it chooses any free port which isn't really useful for server sockets) and call create(). This will bind the socket to any local network adaptor which is chosen by whichever adaptor the incoming connection is using and can be retrieved after connection by address() and port(). If your server socket is for localhost communication only you should use the other constructor specifying the loopback address 127.0.0.1
or ::1 (QHOSTADDRESS_LOCALHOST) - this on many systems internally optimises the connection, making it much faster. Lastly if you want a client socket connecting to some server socket, specify the address and port you want to connect to and call open().
Stream type can be either QBlkSocket::Stream or QBlkSocket::Datagram. The former uses TCP over IP and is a connection-based reliable full-duplex general-purpose data transport protocol. The latter uses UDP over IP and is a connection-less unreliable packet protocol - unreliable means your packets may not receive their destination nor in the same order as sending, however its ability to send status updates much more efficiently than TCP guarantees its usefulness.
For stream-based server sockets you should create() the socket in your monitoring thread, then call waitForConnection() which upon a client connect, returns a new instance of the server socket with a connection to the client. You should at this stage launch another thread to handle monitoring that connection and return to waitForConnection() again.
For datagram-based server sockets, you also call create() - however now you simply try reading from the socket, or else call FX::QIODeviceS::waitForData() if you'd like to poll it. When the read succeeds, peerAddress() and peerPort() will return the source of the datagram until the next read is performed.
Sending data via a datagram-based socket uses the destination address and port as specified in the constructor or to whatever setRequestedAddressAndPort(). If you would like to send data to an arbitrary address and port, use the other writeBlock() overload. Note that you can neither send nor receive any datagrams larger than maxDatagramSize().
A full discussion of the issues surrounding TCP, UDP, IPv4 and IPv6 is beyond the scope of this class documentation, but there are plenty of man pages, MSVC help files, books and RFC's available. Note that by default socket linger is enabled and set to five seconds.
Default security on sockets is full public access and you cannot change this. If you want to control security, consider using FX::QPipe which is more efficient anyway.
Lastly FX::FXConnectionLostException with error code FXEXCEPTION_CONNECTIONLOST is thrown should a connection unexpectedly terminate. You will probably want to trap this for client sockets - for server sockets, you just destroy the instance.
First off, as usual, errors are returned as exceptions rather than by error(). Secondly, a lot of the complexity in QSocketDevice can be avoided as this socket always blocks - thus some API's return default values. I've also removed the methods allowing direct manipulation of the socket handle as code should need to know nothing about it (and this is the biggest break from QSocketDevice's API). Lastly, I've extended the API where it makes sense to make it easier to use.
To create a TCP server socket on port 12345:
QBlkSocket server(QBlkSocket::Stream, (FXushort) 12345); server.create(IO_ReadWrite);
FXPtrHold<QBlkSocket> transport=server.waitForConnection(); FXProcess::threadPool().dispatch(Generic::BindFuncN(clientHandler, transport)); transport=0;
Public Types | |
enum | Type { Stream, Datagram } |
enum | CRLFType { Default, Unix, MacOS, MSDOS } |
enum | UnicodeType { NoTranslation, UTF8, UTF16, UTF16LE, UTF32, UTF32LE } |
typedef FXfval | Offset |
Public Member Functions | |
QBlkSocket (Type type=Stream, FXushort port=0) | |
QBlkSocket (const QHostAddress &addr, FXushort port, Type type=Stream) | |
QBlkSocket (const FXString &addr, FXushort port, Type type=Stream) | |
QBlkSocket (QBlkSocket &o) | |
Type | type () const |
void | setType (Type type) |
const QHostAddress & | address () const |
FXushort | port () const |
QHostAddress | peerAddress () const |
FXushort | peerPort () const |
const QHostAddress & | requestedAddress () const |
FXushort | requestedPort () const |
void | setRequestedAddressAndPort (const QHostAddress &reqAddr, FXushort port) |
bool | isUnique () const |
void | setUnique (bool a) |
FXuval | receiveBufferSize () const |
void | setReceiveBufferSize (FXuval newsize) |
FXuval | sendBufferSize () const |
void | setSendBufferSize (FXuval newsize) |
FXuval | maxDatagramSize () const |
FXint | maxPending () const |
void | setMaxPending (FXint newp) |
bool | listen (int newp) |
bool | addressReusable () const |
void | setAddressReusable (bool newar) |
bool | keepAlive () const |
void | setKeepAlive (bool newar) |
FXint | lingerPeriod () const |
void | setLingerPeriod (FXint period) |
bool | usingNagles () const |
void | setUsingNagles (bool newar) |
bool | connected () const |
bool | create (FXuint mode=IO_ReadWrite) |
bool | open (FXuint mode=IO_ReadWrite) |
void | close () |
void | flush () |
bool | reset () |
FXfval | size () const |
FXDEPRECATEDEXT FXfval | bytesAvailable () const |
virtual const FXACL & | permissions () const |
FXuval | readBlock (char *data, FXuval maxlen) |
FXuval | writeBlock (const char *data, FXuval maxlen) |
FXuval | writeBlock (const char *data, FXuval maxlen, const QHostAddress &addr, FXushort port) |
int | ungetch (int) |
QBlkSocket * | waitForConnection (FXuint waitfor=FXINFINITE) |
FXDEPRECATEDEXT bool | blocking () const |
FXDEPRECATEDEXT void | setBlocking (bool) |
FXDEPRECATEDEXT FXuval | waitForMore (int msecs, bool *timeout=0) |
virtual bool | isSynchronous () const |
virtual void | truncate (FXfval) |
virtual FXfval | at () const |
virtual bool | at (FXfval) |
virtual bool | atEnd () const |
virtual FXuval | readBlockFrom (char *data, FXuval maxlen, FXfval pos) |
FXuval | readBlockFrom (FXuchar *data, FXuval maxlen, FXfval pos) |
virtual FXuval | writeBlockTo (FXfval pos, const char *data, FXuval maxlen) |
FXuval | writeBlockTo (FXfval pos, const FXuchar *data, FXuval maxlen) |
FXuint | flags () const |
FXuint | mode () const |
FXuint | state () const |
CRLFType | crlfFormat () const |
void | setCRLFFormat (CRLFType type) |
UnicodeType | unicodeTranslation () const |
void | setUnicodeTranslation (UnicodeType type) |
bool | isBuffered () const |
bool | isRaw () const |
bool | isTranslated () const |
bool | isUTF16Translated () const |
bool | isUTF32Translated () const |
bool | isReadable () const |
bool | isWriteable () const |
bool | isWritable () const |
bool | isReadWrite () const |
bool | isClosed () const |
bool | isInactive () const |
bool | isOpen () const |
virtual void | setPermissions (const FXACL &) |
FXuval | readBlock (FXuchar *data, FXuval maxlen) |
FXuval | writeBlock (const FXuchar *data, FXuval maxlen) |
virtual FXuval | readLine (char *data, FXuval maxlen) |
virtual int | getch () |
virtual int | putch (int c) |
FXfval | shredData (FXfval offset, FXfval len=(FXfval)-1) |
Static Public Member Functions | |
static bool | waitForData (QIODeviceS **signalled, FXuint no, QIODeviceS **list, FXuint waitfor=FXINFINITE) |
static FXuint | waitForDataMax () throw () |
static UnicodeType | determineUnicodeType (FXuchar *data, FXuval len) throw () |
static FXuval | applyCRLF (FXuchar *FXRESTRICT output, const FXuchar *FXRESTRICT input, FXuval outputlen, FXuval &inputlen, CRLFType crlftype=Default, UnicodeType utftype=NoTranslation) |
static FXuval | removeCRLF (FXuchar *FXRESTRICT output, const FXuchar *FXRESTRICT input, FXuval outputlen, FXuval &inputlen, UnicodeType utftype=NoTranslation) |
Protected Member Functions | |
void | setFlags (int f) |
void | setMode (int m) |
void | setState (int s) |
Protected Attributes | |
FXfval | ioIndex |
Friends | |
FXAPI FXStream & | operator<< (FXStream &s, QIODevice &i) |
FXAPI FXStream & | operator>> (FXStream &s, QIODevice &i) |
enum FX::QBlkSocket::Type |
enum FX::QIODevice::CRLFType [inherited] |
enum FX::QIODevice::UnicodeType [inherited] |
The type of unicode translation you want.
FX::QBlkSocket::QBlkSocket | ( | Type | type = Stream , |
|
FXushort | port = 0 | |||
) |
Constructs a socket on the local machine on port port (you still need to call create()).
FX::QBlkSocket::QBlkSocket | ( | const QHostAddress & | addr, | |
FXushort | port, | |||
Type | type = Stream | |||
) |
Constructs a socket to connect to addr (you still need to call open()) or a server on localhost.
Constructs a socket to connect to whatever addr resolves to by DNS (you still need to call open()) or a server on localhost.
FX::QBlkSocket::QBlkSocket | ( | QBlkSocket & | o | ) |
Destructive copy constructor. Best to not use explicitly.
Type FX::QBlkSocket::type | ( | ) | const |
Returns the type of the socket.
void FX::QBlkSocket::setType | ( | Type | type | ) |
Sets the type of the socket. Closes the socket if already open.
const QHostAddress& FX::QBlkSocket::address | ( | ) | const |
The address of the socket. This will be null until a connection is made.
FXushort FX::QBlkSocket::port | ( | ) | const |
The port of the socket. This will be null until a connection is made.
QHostAddress FX::QBlkSocket::peerAddress | ( | ) | const |
The address of what's connected to the socket. This will be null until a connection is made.
FXushort FX::QBlkSocket::peerPort | ( | ) | const |
The port of what's connected to the socket. This will be null until a connection is made.
const QHostAddress& FX::QBlkSocket::requestedAddress | ( | ) | const |
The address which shall be requested on open() or create() or the next writeBlock() if the socket type is Datagram.
FXushort FX::QBlkSocket::requestedPort | ( | ) | const |
The port which shall be requested on open() or create() or the next writeBlock() if the socket type is Datagram.
void FX::QBlkSocket::setRequestedAddressAndPort | ( | const QHostAddress & | reqAddr, | |
FXushort | port | |||
) |
Sets the address and port which shall be requested on open() or create() or the next writeBlock() if the socket type is Datagram.
bool FX::QBlkSocket::isUnique | ( | ) | const |
Returns true if this socket uses a unique port.
void FX::QBlkSocket::setUnique | ( | bool | a | ) |
Set if you want a socket created using a unique port.
FXuval FX::QBlkSocket::receiveBufferSize | ( | ) | const |
Returns the receive buffer size. Use only after opening.
void FX::QBlkSocket::setReceiveBufferSize | ( | FXuval | newsize | ) |
Sets the receive buffer size. Use only after opening.
FXuval FX::QBlkSocket::sendBufferSize | ( | ) | const |
Returns the send buffer size. Use only after opening.
void FX::QBlkSocket::setSendBufferSize | ( | FXuval | newsize | ) |
Sets the send buffer size. Use only after opening.
FXuval FX::QBlkSocket::maxDatagramSize | ( | ) | const |
Returns the maximum permitted size of a datagram. Any attempt to send or receive more than this amount will fail. Use only after opening.
FXint FX::QBlkSocket::maxPending | ( | ) | const |
Returns the maximum number of pending connections permitted. Defaults to 50.
void FX::QBlkSocket::setMaxPending | ( | FXint | newp | ) |
Sets the maximum number of pending connections.
bool FX::QBlkSocket::addressReusable | ( | ) | const |
Returns true if this socket's address is reusable (never if isUnique() is true). Use only after opening.
void FX::QBlkSocket::setAddressReusable | ( | bool | newar | ) |
Sets if this socket's address is reusable (never if isUnique() is true). Use only after opening.
bool FX::QBlkSocket::keepAlive | ( | ) | const |
Returns true if this socket constantly validates its connection. Use only after opening.
void FX::QBlkSocket::setKeepAlive | ( | bool | newar | ) |
Sets if this socket constantly validates its connection. Use only after opening.
FXint FX::QBlkSocket::lingerPeriod | ( | ) | const |
Returns the period in seconds the socket will wait to send remaining data when closing.
void FX::QBlkSocket::setLingerPeriod | ( | FXint | period | ) |
Sets the period in seconds the socket will wait to send remaining data when closing.
bool FX::QBlkSocket::usingNagles | ( | ) | const |
Returns true if this socket is using Nagle's algorithm. Use only after opening.
void FX::QBlkSocket::setUsingNagles | ( | bool | newar | ) |
Sets if this socket is using Nagle's algorithm. Use only after opening.
bool FX::QBlkSocket::connected | ( | ) | const |
Returns true if the socket is connected to something.
bool FX::QBlkSocket::create | ( | FXuint | mode = IO_ReadWrite |
) | [virtual] |
Creates the socket on the local machine so that others can connect to it. If you specify IO_QuietSocket then the socket is not opened for connections - use listen() to open it for connections later
Implements FX::QIODeviceS.
bool FX::QBlkSocket::open | ( | FXuint | mode = IO_ReadWrite |
) | [virtual] |
Opens a connection to the address previously set. This make take some time.
Implements FX::QIODeviceS.
void FX::QBlkSocket::close | ( | ) | [virtual] |
void FX::QBlkSocket::flush | ( | ) | [virtual] |
bool FX::QBlkSocket::reset | ( | ) |
Resets the socket for use after an error.
FXfval FX::QBlkSocket::size | ( | ) | const [virtual] |
Returns the amount of data waiting to be read. May return ((FXfval)-1) if there is data but it's unknown how much.
Implements FX::QIODevice.
FXDEPRECATEDEXT FXfval FX::QBlkSocket::bytesAvailable | ( | ) | const [inline] |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
virtual const FXACL& FX::QBlkSocket::permissions | ( | ) | const [virtual] |
FXuval FX::QBlkSocket::readBlock | ( | char * | data, | |
FXuval | maxlen | |||
) | [virtual] |
data | Pointer to buffer to receive data | |
maxlen | Maximum number of bytes to read |
Implements FX::QIODevice.
FXuval FX::QBlkSocket::writeBlock | ( | const char * | data, | |
FXuval | maxlen | |||
) | [virtual] |
data | Pointer to buffer of data to send | |
maxlen | Number of bytes to send |
Implements FX::QIODevice.
FXuval FX::QBlkSocket::writeBlock | ( | const char * | data, | |
FXuval | maxlen, | |||
const QHostAddress & | addr, | |||
FXushort | port | |||
) |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. Useful for UDP packet sends
int FX::QBlkSocket::ungetch | ( | int | ) | [virtual] |
QBlkSocket* FX::QBlkSocket::waitForConnection | ( | FXuint | waitfor = FXINFINITE |
) |
FXDEPRECATEDEXT bool FX::QBlkSocket::blocking | ( | ) | const [inline] |
FXDEPRECATEDEXT void FX::QBlkSocket::setBlocking | ( | bool | ) | [inline] |
FXDEPRECATEDEXT FXuval FX::QBlkSocket::waitForMore | ( | int | msecs, | |
bool * | timeout = 0 | |||
) |
virtual bool FX::QIODeviceS::isSynchronous | ( | ) | const [inline, virtual, inherited] |
Returns true if this device is a synchronous device.
Reimplemented from FX::QIODevice.
Reimplemented in FX::QSSLDevice.
virtual void FX::QIODeviceS::truncate | ( | FXfval | ) | [inline, virtual, inherited] |
Does nothing as synchronous devices can't be truncated.
Implements FX::QIODevice.
Reimplemented in FX::QLocalPipe, FX::QPipe, and FX::QSSLDevice.
virtual FXfval FX::QIODeviceS::at | ( | ) | const [inline, virtual, inherited] |
Returns 0 because synchronous devices don't have a current file pointer.
Reimplemented from FX::QIODevice.
Reimplemented in FX::QLocalPipe, FX::QPipe, and FX::QSSLDevice.
virtual bool FX::QIODeviceS::at | ( | FXfval | ) | [inline, virtual, inherited] |
Returns false because you can't set the current file pointer on a synchronous device.
Reimplemented from FX::QIODevice.
Reimplemented in FX::QLocalPipe, FX::QPipe, and FX::QSSLDevice.
virtual bool FX::QIODeviceS::atEnd | ( | ) | const [inline, virtual, inherited] |
Default implementation returning true if size() is zero.
Reimplemented from FX::QIODevice.
Reimplemented in FX::QLocalPipe, FX::QPipe, and FX::QSSLDevice.
virtual FXuval FX::QIODeviceS::readBlockFrom | ( | char * | data, | |
FXuval | maxlen, | |||
FXfval | pos | |||
) | [virtual, inherited] |
Default implementation throws an exception.
Implements FX::QIODevice.
Reimplemented in FX::QSSLDevice.
virtual FXuval FX::QIODeviceS::writeBlockTo | ( | FXfval | pos, | |
const char * | data, | |||
FXuval | maxlen | |||
) | [virtual, inherited] |
Default implementation throws an exception.
Implements FX::QIODevice.
Reimplemented in FX::QSSLDevice.
static bool FX::QIODeviceS::waitForData | ( | QIODeviceS ** | signalled, | |
FXuint | no, | |||
QIODeviceS ** | list, | |||
FXuint | waitfor = FXINFINITE | |||
) | [static, inherited] |
Waits for more data to become available for reading on any one or more of an array of QIODeviceS's specified by list. Precisely which are those left in the array signalled if it's not NULL with empty members being zero.
static FXuint FX::QIODeviceS::waitForDataMax | ( | ) | throw () [static, inherited] |
Returns the maximum number of QIODeviceS's which can be waited for at once.
FXuint FX::QIODevice::flags | ( | ) | const [inline, inherited] |
Returns the flags of this device.
FXuint FX::QIODevice::mode | ( | ) | const [inline, inherited] |
Returns the mode of this device
FXuint FX::QIODevice::state | ( | ) | const [inline, inherited] |
Returns the state of this device
CRLFType FX::QIODevice::crlfFormat | ( | ) | const [inline, inherited] |
Returns the CR/LF format of this device.
void FX::QIODevice::setCRLFFormat | ( | CRLFType | type | ) | [inline, inherited] |
Sets the CR/LF format for output of this device.
UnicodeType FX::QIODevice::unicodeTranslation | ( | ) | const [inline, inherited] |
Returns the unicode translation of this device.
void FX::QIODevice::setUnicodeTranslation | ( | UnicodeType | type | ) | [inline, inherited] |
Sets the unicode translation of this device.
bool FX::QIODevice::isBuffered | ( | ) | const [inline, inherited] |
Returns true if the device is buffered.
bool FX::QIODevice::isRaw | ( | ) | const [inline, inherited] |
Returns true if the device is unbuffered.
bool FX::QIODevice::isTranslated | ( | ) | const [inline, inherited] |
Returns true if the device is LR/CF translated.
bool FX::QIODevice::isUTF16Translated | ( | ) | const [inline, inherited] |
Returns true if the device is UTF-16 translated.
bool FX::QIODevice::isUTF32Translated | ( | ) | const [inline, inherited] |
Returns true if the device is UTF-32 translated.
bool FX::QIODevice::isReadable | ( | ) | const [inline, inherited] |
Returns true if the device is readable.
bool FX::QIODevice::isWriteable | ( | ) | const [inline, inherited] |
Returns true if the device is writeable.
bool FX::QIODevice::isReadWrite | ( | ) | const [inline, inherited] |
Returns true if the device is readable & writeable.
bool FX::QIODevice::isClosed | ( | ) | const [inline, inherited] |
Returns true if the device is closed.
bool FX::QIODevice::isOpen | ( | ) | const [inline, inherited] |
Returns true if the device is opened.
virtual void FX::QIODevice::setPermissions | ( | const FXACL & | ) | [virtual, inherited] |
Sets the ACL for this device.
Reimplemented in FX::QFile, FX::QMemMap, FX::QPipe, and FX::QSSLDevice.
virtual FXuval FX::QIODevice::readLine | ( | char * | data, | |
FXuval | maxlen | |||
) | [virtual, inherited] |
Reads data until an end-of-line or maxlen is exceeded.
virtual int FX::QIODevice::getch | ( | ) | [virtual, inherited] |
Reads a single byte. Returns -1 for no data found.
Reimplemented in FX::QBuffer, FX::QBZip2Device, FX::QGZipDevice, and FX::QMemMap.
virtual int FX::QIODevice::putch | ( | int | c | ) | [virtual, inherited] |
Writes a single byte.
Reimplemented in FX::QBuffer, FX::QBZip2Device, FX::QGZipDevice, and FX::QMemMap.
static UnicodeType FX::QIODevice::determineUnicodeType | ( | FXuchar * | data, | |
FXuval | len | |||
) | throw () [static, inherited] |
Looks at a sample of data and determines what kind of Unicode text it is, returning UnicodeType::NoTranslation if it isn't text. This routine isn't foolproof, but it's a good guess
static FXuval FX::QIODevice::applyCRLF | ( | FXuchar *FXRESTRICT | output, | |
const FXuchar *FXRESTRICT | input, | |||
FXuval | outputlen, | |||
FXuval & | inputlen, | |||
CRLFType | crlftype = Default , |
|||
UnicodeType | utftype = NoTranslation | |||
) | [static, inherited] |
Applies CR/LF and optional UTF-x translation returning bytes output. If outputlen would run out before inputlen can be exhausted it will return early (eg; if mid newline, or mid UTF-x sequence). You should rewind processing to the difference between entrant inputlen and returned inputlen.
static FXuval FX::QIODevice::removeCRLF | ( | FXuchar *FXRESTRICT | output, | |
const FXuchar *FXRESTRICT | input, | |||
FXuval | outputlen, | |||
FXuval & | inputlen, | |||
UnicodeType | utftype = NoTranslation | |||
) | [static, inherited] |
Removes CR/LF translation intelligently (ie; self-adjusts to MS-DOS, Unix and MacOS formats or any mixture of these) and can perform optional UTF-x translation, returning bytes output. If outputlen would run out before inputlen can be exhausted it will return early (eg; if mid newline, or mid UTF-x sequence). You should rewind processing to the difference between entrant inputlen and returned inputlen.
FXfval FX::QIODevice::shredData | ( | FXfval | offset, | |
FXfval | len = (FXfval)-1 | |||
) | [inherited] |
Destroys the len bytes of data from offset offset into the file. Restores the file pointer afterwards and returns how much data was shredded before end of file if encountered. You must have the device open for both reading and writing for this call to succeed.
void FX::QIODevice::setFlags | ( | int | f | ) | [inline, protected, inherited] |
Sets the flags.
void FX::QIODevice::setMode | ( | int | m | ) | [inline, protected, inherited] |
Sets the mode.
void FX::QIODevice::setState | ( | int | s | ) | [inline, protected, inherited] |
Sets the state.
Appends the contents of an i/o device to stream s
Reads all available contents of the stream s to an i/o device, replacing its current contents and resetting the file pointer to the start