replaced my recent GSocket_SetReuseAddr() addition with GSocket_SetReusable() from the patch 992473; it also adds and documents wxSOCKET_REUSEADDR flag

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28494 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2004-07-25 17:06:01 +00:00
parent 733a25f0f4
commit 74c481d117
6 changed files with 69 additions and 37 deletions

View File

@@ -593,6 +593,7 @@ The following flags can be used:
\twocolitem{{\bf wxSOCKET\_NOWAIT}}{Read/write as much data as possible and return immediately.} \twocolitem{{\bf wxSOCKET\_NOWAIT}}{Read/write as much data as possible and return immediately.}
\twocolitem{{\bf wxSOCKET\_WAITALL}}{Wait for all required data to be read/written unless an error occurs.} \twocolitem{{\bf wxSOCKET\_WAITALL}}{Wait for all required data to be read/written unless an error occurs.}
\twocolitem{{\bf wxSOCKET\_BLOCK}}{Block the GUI (do not yield) while reading/writing data.} \twocolitem{{\bf wxSOCKET\_BLOCK}}{Block the GUI (do not yield) while reading/writing data.}
\twocolitem{{\bf wxSOCKET\_REUSEADDR}}{Allows the use of an in-use port (wxServerSocket only)}
\end{twocollist} \end{twocollist}
A brief overview on how to use these flags follows. A brief overview on how to use these flags follows.
@@ -626,6 +627,13 @@ during IO calls, so the GUI will remain blocked until the operation
completes. If it is not used, then the application must take extra completes. If it is not used, then the application must take extra
care to avoid unwanted reentrance. care to avoid unwanted reentrance.
The {\bf wxSOCKET\_REUSEADDR} flag controls the use of the SO_REUSEADDR standard
setsockopt() flag. This flag allows the socket to bind to a port that is already in use.
This is mostly used on UNIX-based systems to allow rapid starting and stopping of a server -
otherwise you may have to wait several minutes for the port to become available.
This option can have suprising platform dependent behavior, check the documentation for
your platforms implementation of setsockopt().
So: So:
{\bf wxSOCKET\_NONE} will try to read at least SOME data, no matter how much. {\bf wxSOCKET\_NONE} will try to read at least SOME data, no matter how much.
@@ -639,6 +647,8 @@ the data.
{\bf wxSOCKET\_BLOCK} has nothing to do with the previous flags and {\bf wxSOCKET\_BLOCK} has nothing to do with the previous flags and
it controls whether the GUI blocks. it controls whether the GUI blocks.
(\bf wxSOCKET\_REUSEADDR} controls special platform-specific behavior for wxServerSocket.
% %
% SetNotify % SetNotify
% %

View File

@@ -235,6 +235,15 @@ GSocket *GSocket_WaitConnection(GSocket *socket);
*/ */
GSocketError GSocket_Connect(GSocket *socket, GSocketStream stream); GSocketError GSocket_Connect(GSocket *socket, GSocketStream stream);
/* GSocket_SetReusable:
* Simply sets the m_resuable flag on the socket. GSocket_SetServer will
* make the appropriate setsockopt() call.
* Implemented as a GSocket function because clients (ie, wxSocketServer)
* don't have access to the GSocket struct information.
* Returns TRUE if the flag was set correctly, FALSE if an error occured
* (ie, if the parameter was NULL)
*/
int GSocket_SetReusable(GSocket *socket);
/* Datagram sockets */ /* Datagram sockets */
@@ -277,7 +286,6 @@ GSocketError GSocket_GetSockOpt(GSocket *socket, int level, int optname,
GSocketError GSocket_SetSockOpt(GSocket *socket, int level, int optname, GSocketError GSocket_SetSockOpt(GSocket *socket, int level, int optname,
const void *optval, int optlen); const void *optval, int optlen);
GSocketError GSocket_SetReuseAddr(GSocket *socket);
void GSocket_Streamed(GSocket *socket); void GSocket_Streamed(GSocket *socket);
void GSocket_Unstreamed(GSocket *socket); void GSocket_Unstreamed(GSocket *socket);

View File

@@ -50,6 +50,7 @@ struct _GSocket
int m_stream; int m_stream;
int m_oriented; int m_oriented;
int m_establishing; int m_establishing;
int m_reusable;
struct timeval m_timeout; struct timeval m_timeout;
/* Callbacks */ /* Callbacks */

View File

@@ -74,7 +74,8 @@ enum
wxSOCKET_NONE = 0, wxSOCKET_NONE = 0,
wxSOCKET_NOWAIT = 1, wxSOCKET_NOWAIT = 1,
wxSOCKET_WAITALL = 2, wxSOCKET_WAITALL = 2,
wxSOCKET_BLOCK = 4 wxSOCKET_BLOCK = 4,
wxSOCKET_REUSEADDR = 8
}; };
enum wxSocketType enum wxSocketType

View File

@@ -1068,6 +1068,11 @@ wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
// Setup the socket as server // Setup the socket as server
GSocket_SetLocal(m_socket, addr_man.GetAddress()); GSocket_SetLocal(m_socket, addr_man.GetAddress());
if (GetFlags() & wxSOCKET_REUSEADDR) {
GSocket_SetReusable(m_socket);
}
if (GSocket_SetServer(m_socket) != GSOCK_NOERROR) if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
{ {
GSocket_destroy(m_socket); GSocket_destroy(m_socket);

View File

@@ -483,6 +483,12 @@ GSocketError GSocket_SetServer(GSocket *sck)
#endif #endif
_GSocket_Enable_Events(sck); _GSocket_Enable_Events(sck);
/* allow a socket to re-bind if the socket is in the TIME_WAIT
state after being previously closed.
*/
if (sck->m_reusable)
setsockopt(socket->m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(u_long));
/* Bind to the local address, /* Bind to the local address,
* retrieve the actual address bound, * retrieve the actual address bound,
* and listen up to 5 connections. * and listen up to 5 connections.
@@ -594,6 +600,16 @@ GSocket *GSocket_WaitConnection(GSocket *socket)
return connection; return connection;
} }
int GSocket_SetReusable(GSocket *socket)
{
/* socket must not be null, and must not be in use/already bound */
if (NULL != socket && socket->m_fd == INVALID_SOCKET) {
socket->m_reusable = TRUE;
return TRUE;
}
return FALSE;
}
/* Client specific parts */ /* Client specific parts */
/* GSocket_Connect: /* GSocket_Connect:
@@ -1144,15 +1160,6 @@ GSocketError GSocket_SetSockOpt(GSocket *socket, int level, int optname,
return GSOCK_OPTERR; return GSOCK_OPTERR;
} }
GSocketError GSocket_SetReuseAddr(GSocket *socket)
{
/* allow a socket to re-bind if the socket is in the TIME_WAIT
state after being previously closed.
*/
u_long arg = 1;
setsockopt(socket->m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(u_long));
}
void GSocket_Streamed(GSocket *socket) void GSocket_Streamed(GSocket *socket)
{ {
socket->m_stream = TRUE; socket->m_stream = TRUE;