Browse Source

split the socket class into StreamingSocket and DatagramSocket

tags/2021-05-28
jules 18 years ago
parent
commit
29421641be
8 changed files with 540 additions and 158 deletions
  1. +1
    -0
      docs/JUCE changelist.txt
  2. +3
    -3
      src/juce_appframework/events/juce_InterprocessConnection.cpp
  3. +2
    -2
      src/juce_appframework/events/juce_InterprocessConnection.h
  4. +2
    -2
      src/juce_appframework/events/juce_InterprocessConnectionServer.cpp
  5. +1
    -1
      src/juce_appframework/events/juce_InterprocessConnectionServer.h
  6. +12
    -0
      src/juce_core/basics/juce_SystemStats.cpp
  7. +340
    -113
      src/juce_core/io/network/juce_Socket.cpp
  8. +179
    -37
      src/juce_core/io/network/juce_Socket.h

+ 1
- 0
docs/JUCE changelist.txt View File

@@ -13,6 +13,7 @@ Changelist for version 1.45
- audio plugins: new methods AudioFilterBase::beginParameterChangeGesture() and endParameterChangeGesture() let you tell the host when a parameter-change action starts and finishes.
- new class: FileSearchPathListComponent, for letting the user edit a FileSearchPath.
- added a critical section option to ReferenceCountedArray
- refactored and added features to the Socket class, replacing it with StreamableSocket (basically the same as the original class), and DatagramSocket.

==============================================================================
Changelist for version 1.44


+ 3
- 3
src/juce_appframework/events/juce_InterprocessConnection.cpp View File

@@ -64,7 +64,7 @@ bool InterprocessConnection::connectToSocket (const String& hostName,
disconnect();
const ScopedLock sl (pipeAndSocketLock);
socket = new Socket();
socket = new StreamingSocket();
if (socket->connect (hostName, portNumber, timeOutMillisecs))
{
@@ -186,7 +186,7 @@ bool InterprocessConnection::sendMessage (const MemoryBlock& message)
}
//==============================================================================
void InterprocessConnection::initialiseWithSocket (Socket* const socket_)
void InterprocessConnection::initialiseWithSocket (StreamingSocket* const socket_)
{
jassert (socket == 0);
socket = socket_;
@@ -324,7 +324,7 @@ void InterprocessConnection::run()
{
if (socket != 0)
{
const int ready = socket->isReady (0);
const int ready = socket->waitUntilReady (true, 0);
if (ready < 0)
{


+ 2
- 2
src/juce_appframework/events/juce_InterprocessConnection.h View File

@@ -180,7 +180,7 @@ public:
private:
CriticalSection pipeAndSocketLock;
Socket* socket;
StreamingSocket* socket;
NamedPipe* pipe;
bool callbackConnectionState;
const bool useMessageThread;
@@ -190,7 +190,7 @@ private:
//==============================================================================
friend class InterprocessConnectionServer;
void initialiseWithSocket (Socket* const socket_);
void initialiseWithSocket (StreamingSocket* const socket_);
void initialiseWithPipe (NamedPipe* const pipe_);
void handleMessage (const Message& message);


+ 2
- 2
src/juce_appframework/events/juce_InterprocessConnectionServer.cpp View File

@@ -53,7 +53,7 @@ bool InterprocessConnectionServer::beginWaitingForSocket (const int portNumber)
{
stop();
socket = new Socket();
socket = new StreamingSocket();
if (socket->createListener (portNumber))
{
@@ -81,7 +81,7 @@ void InterprocessConnectionServer::run()
{
while ((! threadShouldExit()) && socket != 0)
{
Socket* const clientSocket = socket->waitForNextConnection();
StreamingSocket* const clientSocket = socket->waitForNextConnection();
if (clientSocket != 0)
{


+ 1
- 1
src/juce_appframework/events/juce_InterprocessConnectionServer.h View File

@@ -94,7 +94,7 @@ public:
juce_UseDebuggingNewOperator
private:
Socket* volatile socket;
StreamingSocket* volatile socket;
void run();


+ 12
- 0
src/juce_core/basics/juce_SystemStats.cpp View File

@@ -83,10 +83,22 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI()
}
}
#if JUCE_WIN32
// This is imported from the sockets code..
typedef int (__stdcall juce_CloseWin32SocketLibCall) (void);
extern juce_CloseWin32SocketLibCall* juce_CloseWin32SocketLib;
#endif
void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI()
{
if (juceInitialisedNonGUI)
{
#if JUCE_WIN32
// need to shut down sockets if they were used..
if (juce_CloseWin32SocketLib != 0)
(*juce_CloseWin32SocketLib)();
#endif
LocalisedStrings::setCurrentMappings (0);
Thread::stopAllThreads (3000);


+ 340
- 113
src/juce_core/io/network/juce_Socket.cpp View File

@@ -62,76 +62,62 @@ BEGIN_JUCE_NAMESPACE
#include "../../threads/juce_Thread.h"
//==============================================================================
#if JUCE_WIN32
static CriticalSection socketInitLock;
static int numActiveSockets = 0;
#endif
//==============================================================================
Socket::Socket()
: portNumber (0),
handle (-1),
connected (false),
isListener (false)
typedef int (__stdcall juce_CloseWin32SocketLibCall) (void);
juce_CloseWin32SocketLibCall* juce_CloseWin32SocketLib = 0;
static void initWin32Sockets()
{
#if JUCE_WIN32
const ScopedLock sl (socketInitLock);
static CriticalSection lock;
const ScopedLock sl (lock);
if (numActiveSockets++ == 0)
if (juce_CloseWin32SocketLib == 0)
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD (1, 1);
const WORD wVersionRequested = MAKEWORD (1, 1);
WSAStartup (wVersionRequested, &wsaData);
}
#endif
}
Socket::Socket (const String& hostName_, const int portNumber_, const int handle_)
: hostName (hostName_),
portNumber (portNumber_),
handle (handle_),
connected (true),
isListener (false)
{
#if JUCE_WIN32
socketInitLock.enter();
++numActiveSockets;
socketInitLock.exit();
#endif
resetSocketOptions();
juce_CloseWin32SocketLib = &WSACleanup;
}
}
Socket::~Socket()
{
close();
#if JUCE_WIN32
const ScopedLock sl (socketInitLock);
if (--numActiveSockets == 0)
WSACleanup();
#endif
}
//==============================================================================
bool Socket::resetSocketOptions()
static bool resetSocketOptions (const int handle, const bool isDatagram) throw()
{
if (handle <= 0)
return false;
const int sndBufSize = 65536;
const int rcvBufSize = 65536;
const int one = 1;
return setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (int)) == 0
&& setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (int)) == 0
&& setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (int)) == 0;
&& (isDatagram || (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (int)) == 0));
}
//==============================================================================
int Socket::read (void* destBuffer, const int maxBytesToRead)
static bool bindSocketToPort (const int handle, const int port) throw()
{
if (isListener || ! connected)
return -1;
if (handle == 0 || port <= 0)
return false;
struct sockaddr_in servTmpAddr;
zerostruct (servTmpAddr);
servTmpAddr.sin_family = PF_INET;
servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY);
servTmpAddr.sin_port = htons ((uint16) port);
return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0;
}
static int readSocket (const int handle,
void* const destBuffer, const int maxBytesToRead,
bool volatile& connected) throw()
{
int bytesRead = 0;
while (bytesRead < maxBytesToRead)
@@ -162,31 +148,9 @@ int Socket::read (void* destBuffer, const int maxBytesToRead)
return bytesRead;
}
int Socket::write (const void* sourceBuffer, int numBytesToWrite)
{
if (isListener || ! connected)
return -1;
#if JUCE_WIN32
return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0);
#else
int result;
while ((result = ::write (handle, sourceBuffer, numBytesToWrite)) < 0
&& errno == EINTR)
{
}
return result;
#endif
}
//==============================================================================
int Socket::isReady (int timeoutMsecs)
static int waitForReadiness (const int handle, const bool forReading,
const int timeoutMsecs) throw()
{
if (! connected)
return -1;
struct timeval timeout;
struct timeval* timeoutp;
@@ -201,16 +165,21 @@ int Socket::isReady (int timeoutMsecs)
timeoutp = 0;
}
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (handle, &readbits);
fd_set rset, wset;
FD_ZERO (&rset);
FD_SET (handle, &rset);
FD_ZERO (&wset);
FD_SET (handle, &wset);
fd_set* const prset = forReading ? &rset : 0;
fd_set* const pwset = forReading ? 0 : &wset;
#if JUCE_WIN32
if (select (handle + 1, &readbits, 0, 0, timeoutp) < 0)
if (select (handle + 1, prset, pwset, 0, timeoutp) < 0)
return -1;
#else
int result;
while ((result = select (handle + 1, &readbits, 0, 0, timeoutp)) < 0
while ((result = select (handle + 1, prset, pwset, 0, timeoutp)) < 0
&& errno == EINTR)
{
}
@@ -219,33 +188,48 @@ int Socket::isReady (int timeoutMsecs)
return -1;
#endif
if (FD_ISSET (handle, &readbits))
if ((forReading && FD_ISSET (handle, &rset))
|| ((! forReading) && FD_ISSET (handle, &wset)))
return 1;
return 0;
}
//==============================================================================
bool Socket::connect (const String& newHostName,
int newPortNumber,
int timeOutMillisecs)
static bool setSocketBlockingState (const int handle, const bool shouldBlock) throw()
{
if (isListener)
{
jassertfalse // a listener socket can't connect to another one!
#if JUCE_WIN32
u_long nonBlocking = shouldBlock ? 0 : 1;
if (ioctlsocket (handle, FIONBIO, &nonBlocking) != 0)
return false;
}
#else
int socketFlags = fcntl (handle, F_GETFL, 0);
if (connected)
close();
if (socketFlags == -1)
return false;
hostName = newHostName;
portNumber = newPortNumber;
isListener = false;
if (shouldBlock)
socketFlags &= ~O_NONBLOCK;
else
socketFlags |= O_NONBLOCK;
if (fcntl (handle, F_SETFL, socketFlags) != 0)
return false;
#endif
return true;
}
struct hostent* hostEnt = gethostbyname (hostName);
static bool connectSocket (int volatile& handle,
const bool isDatagram,
void** serverAddress,
const String& hostName,
const int portNumber,
const int timeOutMillisecs) throw()
{
struct hostent* const hostEnt = gethostbyname (hostName);
if (! hostEnt)
if (hostEnt == 0)
return false;
struct in_addr targetAddress;
@@ -259,31 +243,136 @@ bool Socket::connect (const String& newHostName,
servTmpAddr.sin_addr = targetAddress;
servTmpAddr.sin_port = htons ((uint16) portNumber);
handle = (int) socket (AF_INET, SOCK_STREAM, 0);
handle = (int) socket (AF_INET, isDatagram ? SOCK_DGRAM : SOCK_STREAM, 0);
if (handle < 0)
return false;
while (timeOutMillisecs > 0 || timeOutMillisecs < 0)
if (isDatagram)
{
if (handle < 0)
return false;
*serverAddress = new struct sockaddr_in();
*((struct sockaddr_in*) *serverAddress) = servTmpAddr;
if (::connect (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0)
{
connected = true;
break;
}
return true;
}
setSocketBlockingState (handle, false);
const int result = ::connect (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in));
if (timeOutMillisecs > 0)
if (result < 0)
{
#if JUCE_WIN32
if (result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
#else
if (result == EINPROGRESS)
#endif
{
const int timeToSleep = jmin (timeOutMillisecs, 1000);
timeOutMillisecs -= timeToSleep;
Thread::sleep (timeToSleep);
if (waitForReadiness (handle, false, timeOutMillisecs) != 1)
return false;
}
}
setSocketBlockingState (handle, true);
resetSocketOptions (handle, false);
return true;
}
//==============================================================================
StreamingSocket::StreamingSocket()
: portNumber (0),
handle (-1),
connected (false),
isListener (false)
{
#if JUCE_WIN32
initWin32Sockets();
#endif
}
StreamingSocket::StreamingSocket (const String& hostName_,
const int portNumber_,
const int handle_)
: hostName (hostName_),
portNumber (portNumber_),
handle (handle_),
connected (true),
isListener (false)
{
#if JUCE_WIN32
initWin32Sockets();
#endif
resetSocketOptions (handle_, false);
}
StreamingSocket::~StreamingSocket()
{
close();
}
//==============================================================================
int StreamingSocket::read (void* destBuffer, const int maxBytesToRead)
{
return (connected && ! isListener) ? readSocket (handle, destBuffer, maxBytesToRead, connected)
: -1;
}
int StreamingSocket::write (const void* sourceBuffer, const int numBytesToWrite)
{
if (isListener || ! connected)
return -1;
#if JUCE_WIN32
return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0);
#else
int result;
while ((result = ::write (handle, sourceBuffer, numBytesToWrite)) < 0
&& errno == EINTR)
{
}
return result;
#endif
}
//==============================================================================
int StreamingSocket::waitUntilReady (const bool readyForReading,
const int timeoutMsecs) const
{
return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs)
: -1;
}
//==============================================================================
bool StreamingSocket::bindToPort (const int port)
{
return bindSocketToPort (handle, port);
}
bool StreamingSocket::connect (const String& remoteHostName,
const int remotePortNumber,
const int timeOutMillisecs)
{
if (isListener)
{
jassertfalse // a listener socket can't connect to another one!
return false;
}
if (connected)
close();
hostName = remoteHostName;
portNumber = remotePortNumber;
isListener = false;
connected = connectSocket (handle, false, 0, remoteHostName,
remotePortNumber, timeOutMillisecs);
if (! (connected && resetSocketOptions()))
if (! (connected && resetSocketOptions (handle, false)))
{
close();
return false;
@@ -292,10 +381,11 @@ bool Socket::connect (const String& newHostName,
return true;
}
void Socket::close()
void StreamingSocket::close()
{
#if JUCE_WIN32
closesocket (handle);
connected = false;
#else
if (connected)
{
@@ -304,7 +394,7 @@ void Socket::close()
if (isListener)
{
// need to do this to interrupt the accept() function..
Socket temp;
StreamingSocket temp;
temp.connect ("localhost", portNumber, 1000);
}
}
@@ -315,12 +405,11 @@ void Socket::close()
hostName = String::empty;
portNumber = 0;
handle = -1;
connected = false;
isListener = false;
}
//==============================================================================
bool Socket::createListener (int newPortNumber)
bool StreamingSocket::createListener (const int newPortNumber)
{
if (connected)
close();
@@ -354,7 +443,7 @@ bool Socket::createListener (int newPortNumber)
return true;
}
Socket* Socket::waitForNextConnection()
StreamingSocket* StreamingSocket::waitForNextConnection() const
{
jassert (isListener || ! connected); // to call this method, you first have to use createListener() to
// prepare this socket as a listener.
@@ -371,15 +460,153 @@ Socket* Socket::waitForNextConnection()
const int newSocket = (int) accept (handle, &address, &len);
if (newSocket >= 0 && connected)
return new Socket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr),
portNumber, newSocket);
return new StreamingSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr),
portNumber, newSocket);
}
return 0;
}
bool StreamingSocket::isLocal() const throw()
{
return hostName == T("127.0.0.1");
}
//==============================================================================
//==============================================================================
DatagramSocket::DatagramSocket (const int localPortNumber)
: portNumber (0),
handle (-1),
connected (false),
serverAddress (0)
{
#if JUCE_WIN32
initWin32Sockets();
#endif
bindToPort (localPortNumber);
}
DatagramSocket::DatagramSocket (const String& hostName_, const int portNumber_,
const int handle_, const int localPortNumber)
: hostName (hostName_),
portNumber (portNumber_),
handle (handle_),
connected (true),
serverAddress (0)
{
#if JUCE_WIN32
initWin32Sockets();
#endif
resetSocketOptions (handle_, true);
bindToPort (localPortNumber);
}
DatagramSocket::~DatagramSocket()
{
close();
delete ((struct sockaddr_in*) serverAddress);
serverAddress = 0;
}
void DatagramSocket::close()
{
#if JUCE_WIN32
closesocket (handle);
connected = false;
#else
connected = false;
::close (handle);
#endif
hostName = String::empty;
portNumber = 0;
handle = -1;
}
bool DatagramSocket::bindToPort (const int port)
{
return bindSocketToPort (handle, port);
}
bool DatagramSocket::connect (const String& remoteHostName,
const int remotePortNumber,
const int timeOutMillisecs)
{
if (connected)
close();
hostName = remoteHostName;
portNumber = remotePortNumber;
connected = connectSocket (handle, true, &serverAddress,
remoteHostName, remotePortNumber,
timeOutMillisecs);
if (! (connected && resetSocketOptions (handle, true)))
{
close();
return false;
}
return true;
}
DatagramSocket* DatagramSocket::waitForNextConnection() const
{
struct sockaddr address;
#if defined (JUCE_LINUX) || (defined (JUCE_MAC) && ! MACOS_10_2_OR_EARLIER)
socklen_t len = sizeof (sockaddr);
#else
int len = sizeof (sockaddr);
#endif
while (waitUntilReady (true, -1) == 1)
{
char buf[1];
if (recvfrom (handle, buf, 0, 0, &address, &len) > 0)
{
return new DatagramSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr),
ntohs (((struct sockaddr_in*) &address)->sin_port),
-1, -1);
}
}
return 0;
}
//==============================================================================
bool Socket::isLocal() const throw()
int DatagramSocket::waitUntilReady (const bool readyForReading,
const int timeoutMsecs) const
{
return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs)
: -1;
}
int DatagramSocket::read (void* destBuffer, const int maxBytesToRead)
{
return connected ? readSocket (handle, destBuffer, maxBytesToRead, connected)
: -1;
}
int DatagramSocket::write (const void* sourceBuffer, const int numBytesToWrite)
{
// You need to call connect() first to set the server address..
jassert (serverAddress != 0 && connected);
return connected ? sendto (handle, (const char*) sourceBuffer,
numBytesToWrite, 0,
(const struct sockaddr*) serverAddress,
sizeof (struct sockaddr_in))
: -1;
}
bool DatagramSocket::isLocal() const throw()
{
return hostName == T("127.0.0.1");
}


+ 179
- 37
src/juce_core/io/network/juce_Socket.h View File

@@ -37,14 +37,14 @@
//==============================================================================
/**
A wrapper for a socket.
A wrapper for a streaming (TCP) socket.
Allows low-level use of sockets; for an easier-to-use messaging layer on top of
This allows low-level use of sockets; for an easier-to-use messaging layer on top of
sockets, you could also try the InterprocessConnection class.
@see InterprocessConnection, InterprocessConnectionServer
@see DatagramSocket, InterprocessConnection, InterprocessConnectionServer
*/
class JUCE_API Socket
class JUCE_API StreamingSocket
{
public:
//==============================================================================
@@ -57,49 +57,37 @@ public:
enters "listener" mode, and can be used to spawn new sockets for each connection
that comes along.
*/
Socket();
StreamingSocket();
/** Destructor. */
~Socket();
~StreamingSocket();
//==============================================================================
// Tests if the socket is ready
// Returns: 1 == yes, 0 == no, -1 == error
int isReady (int timeoutMsecs = 0);
/** Binds the socket to the specified local port.
//==============================================================================
/** Reads bytes from the socket (blocking).
Returns the number of bytes read, or -1 if there was an error.
*/
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.
@returns true on success; false may indicate that another socket is already bound
on the same port
*/
int write (const void* sourceBuffer, int numBytesToWrite);
bool bindToPort (const int localPortNumber);
//==============================================================================
/** Tries to connect the socket to hostname:port.
Returns true if it succeeds.
If timeOutMillisecs is 0, then this method will block until the operating system
rejects the connection (which could take a long time).
@returns true if it succeeds.
@see isConnected
*/
bool connect (const String& hostname,
int portNumber,
int timeOutMillisecs = 3000);
bool connect (const String& remoteHostname,
const int remotePortNumber,
const int timeOutMillisecs = 3000);
/** Closes the connection. */
void close();
//==============================================================================
/** True if the socket is currently connected. */
bool isConnected() const throw() { return connected; }
/** Closes the connection. */
void close();
/** Returns the name of the currently connected host. */
const String& getHostName() const throw() { return hostName; }
@@ -109,6 +97,39 @@ public:
/** True if the socket is connected to this machine rather than over the network. */
bool isLocal() const throw();
//==============================================================================
/** Waits until the socket is ready for reading or writing.
If readyForReading is true, it will wait until the socket is ready for
reading; if false, it will wait until it's ready for writing.
If the timeout is < 0, it will wait forever, or else will give up after
the specified time.
If the socket is ready on return, this returns 1. If it times-out before
the socket becomes ready, it returns 0. If an error occurs, it returns -1.
*/
int waitUntilReady (const bool readyForReading,
const int timeoutMsecs) const;
/** Reads bytes from the socket (blocking).
Note that this method will block unless you have checked the socket is ready
for reading before calling it (see the waitUntilReady() method).
@returns the number of bytes read, or -1 if there was an error.
*/
int read (void* destBuffer, const int maxBytesToRead);
/** Writes bytes to the socket from a buffer.
Note that this method will block unless you have checked the socket is ready
for writing before calling it (see the waitUntilReady() method).
@returns the number of bytes written, or -1 if there was an error.
*/
int write (const void* sourceBuffer, const int numBytesToWrite);
//==============================================================================
/** Puts this socket into "listener" mode.
@@ -120,7 +141,7 @@ public:
@see waitForNextConnection
*/
bool createListener (int portNumber);
bool createListener (const int portNumber);
/** When in "listener" mode, this waits for a connection and spawns it as a new
socket.
@@ -131,7 +152,7 @@ public:
@see createListener
*/
Socket* waitForNextConnection();
StreamingSocket* waitForNextConnection() const;
//==============================================================================
@@ -142,11 +163,132 @@ private:
int volatile portNumber, handle;
bool connected, isListener;
Socket (const String& hostname, const int portNumber, const int handle);
Socket (const Socket&);
const Socket& operator= (const Socket&);
StreamingSocket (const String& hostname, const int portNumber, const int handle);
StreamingSocket (const StreamingSocket&);
const StreamingSocket& operator= (const StreamingSocket&);
};
//==============================================================================
/**
A wrapper for a datagram (UDP) socket.
This allows low-level use of sockets; for an easier-to-use messaging layer on top of
sockets, you could also try the InterprocessConnection class.
@see StreamingSocket, InterprocessConnection, InterprocessConnectionServer
*/
class JUCE_API DatagramSocket
{
public:
//==============================================================================
/**
Creates an (uninitialised) datagram socket.
The localPortNumber is the port on which to bind this socket. If this value is 0,
the port number is assigned by the operating system.
To use the socket for sending, call the connect() method. This will not immediately
make a connection, but will save the destination you've provided. After this, you can
call read() or write().
To wait for other sockets to connect to this one, call waitForNextConnection().
*/
DatagramSocket (const int localPortNumber);
/** Destructor. */
~DatagramSocket();
//==============================================================================
/** Binds the socket to the specified local port.
@returns true on success; false may indicate that another socket is already bound
on the same port
*/
bool bindToPort (const int localPortNumber);
/** Tries to connect the socket to hostname:port.
If timeOutMillisecs is 0, then this method will block until the operating system
rejects the connection (which could take a long time).
@returns true if it succeeds.
@see isConnected
*/
bool connect (const String& remoteHostname,
const int remotePortNumber,
const int timeOutMillisecs = 3000);
/** True if the socket is currently connected. */
bool isConnected() const throw() { return connected; }
/** Closes the connection. */
void close();
/** 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; }
/** True if the socket is connected to this machine rather than over the network. */
bool isLocal() const throw();
//==============================================================================
/** Waits until the socket is ready for reading or writing.
If readyForReading is true, it will wait until the socket is ready for
reading; if false, it will wait until it's ready for writing.
If the timeout is < 0, it will wait forever, or else will give up after
the specified time.
If the socket is ready on return, this returns 1. If it times-out before
the socket becomes ready, it returns 0. If an error occurs, it returns -1.
*/
int waitUntilReady (const bool readyForReading,
const int timeoutMsecs) const;
/** Reads bytes from the socket (blocking).
Note that this method will block unless you have checked the socket is ready
for reading before calling it (see the waitUntilReady() method).
@returns the number of bytes read, or -1 if there was an error.
*/
int read (void* destBuffer, const int maxBytesToRead);
/** Writes bytes to the socket from a buffer.
Note that this method will block unless you have checked the socket is ready
for writing before calling it (see the waitUntilReady() method).
@returns the number of bytes written, or -1 if there was an error.
*/
int write (const void* sourceBuffer, const int numBytesToWrite);
//==============================================================================
/** This waits for incoming data to be sent, and returns a socket that can be used
to read it.
The object that gets returned is owned by the caller, and can't be used for
sending, but can be used to read the data.
*/
DatagramSocket* waitForNextConnection() const;
//==============================================================================
juce_UseDebuggingNewOperator
private:
String hostName;
int volatile portNumber, handle;
bool connected;
void* serverAddress;
bool resetSocketOptions();
DatagramSocket (const String& hostname, const int portNumber, const int handle, const int localPortNumber);
DatagramSocket (const DatagramSocket&);
const DatagramSocket& operator= (const DatagramSocket&);
};


Loading…
Cancel
Save