1414# include < winsock2.h>
1515# include < ws2tcpip.h>
1616using socket_t = SOCKET ;
17+ constexpr socket_t kInvalidSocket = INVALID_SOCKET ;
1718# define SM_CLOSE_SOCKET closesocket
1819#else
1920# include < arpa/inet.h>
2021# include < netinet/in.h>
2122# include < sys/socket.h>
2223# include < unistd.h>
2324using socket_t = int ;
25+ constexpr socket_t kInvalidSocket = -1 ;
2426# define SM_CLOSE_SOCKET ::close
2527#endif
2628
@@ -32,6 +34,26 @@ namespace System::ServiceModel {
3234
3335namespace {
3436
37+ bool IsInvalidSocket (socket_t socket)
38+ {
39+ return socket == kInvalidSocket ;
40+ }
41+
42+ void InitializeSockets ()
43+ {
44+ #if defined(_WIN32)
45+ static std::once_flag initialized;
46+ static int result = 0 ;
47+ std::call_once (initialized, [] {
48+ WSADATA data{};
49+ result = ::WSAStartup (MAKEWORD (2 , 2 ), &data);
50+ });
51+ if (result != 0 ) {
52+ throw CommunicationException (" ServiceHost: could not initialize Windows sockets." );
53+ }
54+ #endif
55+ }
56+
3557std::string LocalName (const std::string& name)
3658{
3759 const std::size_t colon = name.find (' :' );
@@ -185,8 +207,9 @@ void ServiceHost::Open()
185207 }
186208 }
187209
210+ InitializeSockets ();
188211 const socket_t listener = ::socket (AF_INET , SOCK_STREAM , 0 );
189- if (listener < 0 ) {
212+ if (IsInvalidSocket ( listener) ) {
190213 throw CommunicationException (" ServiceHost: could not create a listening socket." );
191214 }
192215
@@ -205,16 +228,17 @@ void ServiceHost::Open()
205228 throw CommunicationException (" ServiceHost: could not listen on " + uri + " ." );
206229 }
207230
208- listenSocket_ = static_cast <int >(listener);
231+ listenSocket_ = static_cast <std:: uintptr_t >(listener);
209232 open_ = true ;
210- listener_ = std::thread ([this ] { Listen (); });
233+ listener_ = std::thread ([this , listenerSocket = *listenSocket_ ] { Listen (listenerSocket ); });
211234}
212235
213- void ServiceHost::Listen ()
236+ void ServiceHost::Listen (std:: uintptr_t listenerSocket )
214237{
238+ const socket_t listener = static_cast <socket_t >(listenerSocket);
215239 while (open_) {
216- const socket_t connection = ::accept (static_cast < socket_t >(listenSocket_) , nullptr , nullptr );
217- if (connection < 0 ) {
240+ const socket_t connection = ::accept (listener , nullptr , nullptr );
241+ if (IsInvalidSocket ( connection) ) {
218242 if (!open_) {
219243 break ;
220244 }
@@ -331,19 +355,20 @@ void ServiceHost::Close()
331355
332356 open_ = false ;
333357
334- if (listenSocket_ >= 0 ) {
358+ if (listenSocket_.has_value ()) {
359+ const socket_t listener = static_cast <socket_t >(*listenSocket_);
335360#if defined(_WIN32)
336- ::shutdown (static_cast < socket_t >(listenSocket_) , SD_BOTH);
361+ ::shutdown (listener , SD_BOTH );
337362#else
338- ::shutdown (static_cast < socket_t >(listenSocket_) , SHUT_RDWR);
363+ ::shutdown (listener , SHUT_RDWR );
339364#endif
340- SM_CLOSE_SOCKET (static_cast <socket_t >(listenSocket_));
341- listenSocket_ = -1 ;
365+ SM_CLOSE_SOCKET (listener);
342366 }
343367
344368 if (listener_.joinable ()) {
345369 listener_.join ();
346370 }
371+ listenSocket_.reset ();
347372}
348373
349374} // namespace System::ServiceModel
0 commit comments