Hi Jules,
Would you accept some addition to Juce’s socket, if implemented like this:
class JUCE_API Socket
{
public:
//==============================================================================
/** Creates an uninitialised stream socket.
To connect it, use the connect() method, after which you can read() or write()
to it.
To wait for other sockets to connect to this one, the createListener() method
enters "listener" mode, and can be used to spawn new sockets for each connection
that comes along.
This is typical TCP socket.
*/
Socket();
/** Creates an uninitialised datagram socket.
The localPort is the port on which to bind the socket before commiting any transmission.
If set to 0, the localPort is assigned by the operating system.
To use it, you can call the connect() method. This method will not perform any
connection at all, but instead save the destination you've provided.
After this, you can read() or write() to it, the same destination will be used.
To wait for other sockets to connect to this one, you can directly
waitForNewConnection().
This is typical UDP socket.
*/
Socket(int localPort);
/** Destructor. */
~Socket();
//==============================================================================
// Tests if the socket is ready
// Returns: 1 == yes, 0 == no, -1 == error
int isReady (int timeoutMsecs = 0);
/** Test whether a socket is ready for reading or writing.
If the socket is ready for any communication, you can write & read to/from it,
without being blocked.
Returns true if the socket is ready for the mode you've specified, false otherwise.
@warning Don't poll with this method, prefer using waitForStateChange instead.
@see read, write, waitForStateChange
*/
bool isReadyForCommunication(bool writing);
/** Wait on this socket state change.
Yield the current thread until the socket state you're monitoring changed,
or a timeout expired
Returns true if the wait succeeded, false on timeout or error
@see read, write, isReadyForCommunication
*/
bool waitForStateChange(bool monitorReadingState, bool monitorWritingState, int timeOutMillisecs = 300);
/** Optimise the socket transfers when streaming large amount of data.
Use this method if you're receiving large amount of data in small time on datagram based sockets,
or you want to trash the remnant packets while closing a communication.
For typical usage you shouldn't need this method.
However, for streaming & low-latency communication, it's required.
For datagram sockets, this method will create a larger buffer in kernel space, so you won't miss
any packet anymore.
For stream sockets, this method will stop lingering, so you can effectively close a socket faster.
The other side must have a kind of "watchdog" mode, or the other side will never know the socket
communication has been broken. This is only useful on very slow links, where round trip time is
very high.
Returns true on success
*/
bool optimizeSocketForStreaming();
//==============================================================================
/** Reads bytes from the socket (blocking).
Returns the number of bytes read, or -1 if there was an error.
@warning This method will block unless you have checked the socket is ready for reading before.
*/
int read (void* destBuffer, const int maxBytesToRead);
/** Writes bytes to the socket from a buffer.
This may block on error conditions.
Returns the number of bytes written, or -1 if there was an error.
@warning This method will block unless you have checked the socket is ready for writing before.
*/
int write (const void* sourceBuffer, int numBytesToWrite);
//==============================================================================
/** Tries to connect the socket to hostname:port.
If timeOutMillisecs is 0, then the connect will block until operating system
reject the connection (which can be very long).
Returns true if it succeeds.
@see isConnected
*/
bool connect (const String& hostname,
int portNumber,
int timeOutMillisecs = 3000);
/** Closes the connection. */
void close();
//==============================================================================
/** True if the socket is currently connected. */
bool isConnected() const throw() { return connected; }
/** Returns the name of the currently connected host. */
const String& getHostName() const throw() { return hostName; }
/** Returns the port number that's currently open. */
int getPort() const throw() { return portNumber; }
/** Bind the socket on the specified port.
This must be done before any connection
Returns true on success, false may indicate that another socket is already bound on that port
*/
bool bindOnPort(const int port) throw();
/** True if the socket is connected to this machine rather than over the network. */
bool isLocal() const throw();
//==============================================================================
/** Puts this socket into "listener" mode.
When in this mode, your thread can call waitForNextConnection() repeatedly,
which will spawn new sockets for each new connection, so that these can
be handled in parallel by other threads.
This returns true if it manages to open the socket successfully.
@see waitForNextConnection
*/
bool createListener (int portNumber);
/** When in "listener" mode, this waits for a connection and spawns it as a new
socket.
The object that gets returned will be owned by the caller.
This method can only be called after using createListener().
@see createListener
*/
Socket* waitForNextConnection();
[...]
