Protovision/socketstream

Not working on Windows

Closed this issue · 5 comments

dbrbs commented

Hello! I cloned this repo on my Windows 10 laptop, and I tried running the server and client examples, but it doesn't seem to compile. It gives errors from the winsock_native_socket_traits.hh file, all along the lines of error: '::getaddrinfo' was not declared in this scope. The same goes for ::freeaddrinfo and ::getnameinfo. Is there a way to fix this? Thanks!

If you are using the Visual C++ compiler, the commands:

cl /EHsc server_example.cc ws2_32.lib
cl /EHsc client_example.cc ws2_32.lib

should compile the example programs when issued from a Developer Command Prompt for VS.

If you are using the MinGW compiler, then the commands would be:

g++ -D _WIN32 -o client_example.exe client_example.cc -lws2_32
g++ -D _WIN32 -o server_example.exe server_example.cc -lws2_32

After compiling successfully, to test the programs first run:

server_example.exe 6789

in one terminal window, then run

client_example.exe localhost 6789

In another terminal window and begin entering lines of text into the client terminal window to see the server echo them back.

I can vouch for this. I am also getting a similar error when using it on Windows.

OS: Windows 10 ver. 1809

Steps to reproduce:

  1. Clone the repo
  2. Create a file:
#include "socketstream/socketstream.hh"

int main()
{}
  1. Compile (using MinGW gcc 8.2.0) with g++ main.cpp
  2. Error:
In file included from socketstream/src/native_socket_traits.hh:18,
                 from socketstream/socketstream.hh:6,
                 from main.cpp:1:
socketstream/src/detail/winsock_native_socket_traits.hh: In static member function 'static swoope::native_socket_traits::socket_type swoope::native_socket_traits::open(const string&, const string&)':
socketstream/src/detail/winsock_native_socket_traits.hh:37:10: error: '::getaddrinfo' has not been declared
    if (::getaddrinfo(host.c_str(), service.c_str(),
          ^~~~~~~~~~~
socketstream/src/detail/winsock_native_socket_traits.hh:37:10: note: suggested alternative: 'addrinfo'
    if (::getaddrinfo(host.c_str(), service.c_str(),
          ^~~~~~~~~~~
          addrinfo
socketstream/src/detail/winsock_native_socket_traits.hh:46:6: error: '::freeaddrinfo' has not been declared
    ::freeaddrinfo(ai);
      ^~~~~~~~~~~~
socketstream/src/detail/winsock_native_socket_traits.hh:46:6: note: suggested alternative: 'addrinfo'
    ::freeaddrinfo(ai);
      ^~~~~~~~~~~~
      addrinfo
socketstream/src/detail/winsock_native_socket_traits.hh: In static member function 'static swoope::native_socket_traits::socket_type swoope::native_socket_traits::open(const string&, int)':
socketstream/src/detail/winsock_native_socket_traits.hh:62:10: error: '::getaddrinfo' has not been declared
    if (::getaddrinfo(0, service.c_str(), &hints, &ai) != 0)
          ^~~~~~~~~~~
socketstream/src/detail/winsock_native_socket_traits.hh:62:10: note: suggested alternative: 'addrinfo'
    if (::getaddrinfo(0, service.c_str(), &hints, &ai) != 0)
          ^~~~~~~~~~~
          addrinfo
socketstream/src/detail/winsock_native_socket_traits.hh:76:6: error: '::freeaddrinfo' has not been declared
    ::freeaddrinfo(ai);
      ^~~~~~~~~~~~
socketstream/src/detail/winsock_native_socket_traits.hh:76:6: note: suggested alternative: 'addrinfo'
    ::freeaddrinfo(ai);
      ^~~~~~~~~~~~
      addrinfo
socketstream/src/detail/winsock_native_socket_traits.hh: In static member function 'static std::__cxx11::string swoope::native_socket_traits::sockaddr_storage_to_string(SOCKADDR_STORAGE*)':
socketstream/src/detail/winsock_native_socket_traits.hh:93:10: error: '::getnameinfo' has not been declared
    if (::getnameinfo((const SOCKADDR*)ss,
          ^~~~~~~~~~~

I installed MinGW GCC 8.2.0 and I found the following code in include/ws2tcpip.h:

#if (_WIN32_WINNT >= 0x0501)
void WSAAPI freeaddrinfo (struct addrinfo*);
int WSAAPI getaddrinfo (const char*,const char*,const struct addrinfo*,
		        struct addrinfo**);
int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
		       char*,DWORD,int);
#else
/* FIXME: Need WS protocol-independent API helpers.  */
#endif

The constant 0x501 represents Windows XP which corresponds to the following constants from include/sdkddkver.h:

/* Version constants specifying _WIN32_WINNT versions; these are defined at
 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa383745(v=vs.85).aspx
 * (values for legacy platforms have been inferred from historical knowledge).
 */
#define _WIN32_WINNT_NT4	0x0400		/* Windows NT4 */
#define _WIN32_WINNT_NT4E	0x0401		/* Windows NT4E */
#define _WIN32_WINNT_NT4SP3	0x0403		/* Windows NT4 + ServicePack 3 */
#define _WIN32_WINDOWS_95	0x0400		/* Windows 95 */
#define _WIN32_WINDOWS_98	0x0410		/* Windows 98 */
#define _WIN32_WINDOWS_ME	0x0490		/* Windows Millenium Edition */
#define _WIN32_WINNT_WIN2K	0x0500		/* Windows 2000 */
#define _WIN32_WINNT_WINXP	0x0501		/* Windows XP */
#define _WIN32_WINNT_WS03	0x0502		/* Windows Server 2003 */
#define _WIN32_WINNT_WIN6	0x0600		/* Alias for Windows Vista */
#define _WIN32_WINNT_VISTA	0x0600		/* Windows Vista */
#define _WIN32_WINNT_WS08	0x0600		/* Windows Server 2008 */
#define _WIN32_WINNT_LONGHORN	0x0600		/* Alias for Windows Vista */
#define _WIN32_WINNT_WIN7	0x0601		/* Windows 7 */
#define _WIN32_WINNT_WIN8	0x0602		/* Windows 8 */
#define _WIN32_WINNT_WINBLUE	0x0603		/* Windows 8.1 */

The undefined references to getaddrinfo, freeaddrinfo, and getnameinfo are due to _WIN32_WINNT being defined with a value lower than 0x501 with MinGW. I will add code to fix this. In the meantime, use:

-D _WIN32_WINNT=0x501

with MinGW g++.

I pushed a fix for this. The following code has been added to the beginning of src/detail/winsock_native_socket_traits.hh:

#ifdef _WIN32_WINNT
#if _WIN32_WINNT < 0x501
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x501
#endif
#else
#define _WIN32_WINNT 0x501
#endif
dbrbs commented

Hello, it works now. Thank you so much!

(For others looking at this issue, don't forget -lws2_32 when compiling)