Advertisement
HisRoyalRedness

StackOverflow question

Feb 12th, 2013
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.07 KB | None | 0 0
  1. #define WIN32_LEAN_AND_MEAN
  2.  
  3. //http://stackoverflow.com/questions/14823635/winsock-bind-before-connects-results-in-wsaeaddrnotavail-the-requested-address
  4.  
  5. #include <windows.h>
  6. #include <winsock2.h>
  7. #include <ws2tcpip.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <iostream>
  11. #include <string>
  12. #include <vector>
  13.  
  14. // Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
  15. #pragma comment (lib, "Ws2_32.lib")
  16. #pragma comment (lib, "Mswsock.lib")
  17. #pragma comment (lib, "AdvApi32.lib")
  18.  
  19. using std::cout;
  20. using std::endl;
  21. using std::vector;
  22. using std::string;
  23. using std::exception;
  24.  
  25. const int MAX_INTERFACES = 20;
  26. const int DEFAULT_BUFLEN = 1024;
  27. const char * DEFAULT_HOST = "10.60.35.10";
  28. const char * DEFAULT_PORT = "80";
  29.  
  30. class WSAException : public exception
  31. {
  32. public:
  33.     WSAException(string message);
  34.     virtual const char* what() const throw() { return _fullMessage.c_str(); }
  35.     int errorCode() { return _errorCode; }
  36.  
  37. private:
  38.     int _errorCode;
  39.     string _fullMessage;
  40. };
  41.  
  42. void throwIfError(int result, string msg);
  43. void throwIfError(WSAException ex);
  44. void getLocalAddresses(vector<sockaddr> & localAddresses, ULONG subnet, ULONG subnetMask);
  45. void getServerAddresses(vector<sockaddr> & serverAddresses, string host, string port);
  46. std::ostream& operator<<(std::ostream& os, const sockaddr_in& addr);
  47. std::ostream& operator<<(std::ostream& os, const sockaddr& addr);
  48. template<class T> int inline findAndReplace(T& source, const T& find, const T& replace);
  49.  
  50.  
  51. int main(int argc, char* argv[])
  52. {
  53.     WSADATA wsaData;
  54.     int iResult;
  55.     char buffer[DEFAULT_BUFLEN];
  56.  
  57.     // Get default server hostname
  58.     string host(argc != 2 ? DEFAULT_HOST : argv[1]);
  59.  
  60.     // Build HTTP request
  61.     string request = "GET http://";
  62.     request += host;
  63.     request += " HTTP/1.0\r\nHost: ";
  64.     request += host;
  65.     request += "\r\n\r\n";
  66.  
  67.     try
  68.     {
  69.         // Initialize Winsock
  70.         throwIfError(WSAStartup(MAKEWORD(2,2), &wsaData), "WSAStartup failed with error");
  71.  
  72.         // Get a vector of all local addresses on the 10.0.0.0 subnet
  73.         vector<sockaddr> localAddresses;
  74.         getLocalAddresses(localAddresses, 0x0a, 0xff);
  75.  
  76.         // Get a vector of server addresses
  77.         vector<sockaddr> remoteAddresses;
  78.         getServerAddresses(remoteAddresses, host, DEFAULT_PORT);
  79.  
  80.         auto localAddress = localAddresses.begin();
  81.         while(true)
  82.         {
  83.             // Select the next local address in turn, looping back to the start when we reach the end
  84.             if (++localAddress == localAddresses.end())
  85.                 localAddress = localAddresses.begin();
  86.  
  87.             // Select the first server address (won't worry about any others for now)
  88.             sockaddr remoteAddr = *remoteAddresses.begin();
  89.  
  90.             // Create a SOCKET for connecting to server
  91.             SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  92.             throwIfError(sock, "Socket creation failed");
  93.  
  94.             // Bind the socket locally to a specific interface
  95.             iResult = bind(sock, &*localAddress, sizeof(*localAddress));
  96.             WSAException ex1("Unable to bind to local net");
  97.             cout << "BIND result (" << iResult << ") binding locally to " << *localAddress << endl;
  98.             throwIfError(ex1);
  99.  
  100.             // Connect to the server.
  101.             iResult = connect( sock, &remoteAddr, sizeof(remoteAddr));
  102.             WSAException ex2("Unable to connect to server");
  103.             cout << "CONNECT result (" << iResult << ") connecting remotely to " << remoteAddr << endl;
  104.             throwIfError(ex2);
  105.  
  106.             // Send an initial buffer
  107.             int bytesSent = send( sock, request.c_str(), request.length(), 0 );
  108.             WSAException ex3("Send error");
  109.             cout << "Bytes Sent: " << bytesSent << endl;
  110.             throwIfError(ex3);
  111.  
  112.             // Receive until the peer closes the connection
  113.             string response = "    ";
  114.             int responseLen = DEFAULT_BUFLEN;
  115.             do
  116.             {
  117.                 responseLen = recv(sock, (char*)&buffer, DEFAULT_BUFLEN, 0);
  118.                 if ( responseLen > 0 )
  119.                     response+= string(buffer).substr(0,responseLen);
  120.                 else if ( responseLen == 0 )
  121.                     cout << "Connection closed" << endl;
  122.                 else
  123.                     cout << WSAException("recv failed").what() << endl;
  124.  
  125.             } while( responseLen > 0);
  126.  
  127.             // Indent the html response so that the console is not so cluttered
  128.             findAndReplace(response, string("\n"), string("\n    "));
  129.             cout << response << endl << endl << endl << endl;
  130.  
  131.             // cleanup
  132.             closesocket(sock);
  133.         }
  134.     }
  135.     catch(WSAException& ex)
  136.     {
  137.         cout << ex.what() << endl;
  138.     }
  139.     catch(exception& ex)
  140.     {
  141.         cout << ex.what() << endl;;
  142.     }
  143.  
  144.     WSACleanup();
  145.     return 0;
  146. }
  147.  
  148. void getServerAddresses(vector<sockaddr> & serverAddresses, string host, string port)
  149. {
  150.     // Resolve the server address(es) and port
  151.     addrinfo *servAddr = NULL;
  152.     struct addrinfo hints;
  153.     ZeroMemory( &hints, sizeof(hints) );
  154.     hints.ai_flags = AI_NUMERICSERV;
  155.     hints.ai_family = AF_UNSPEC;
  156.     hints.ai_socktype = SOCK_STREAM;
  157.     hints.ai_protocol = IPPROTO_TCP;
  158.  
  159.     throwIfError(getaddrinfo(host.c_str(), port.c_str(), &hints, &servAddr), "getaddrinfo failed");
  160.  
  161.     struct addrinfo *serverAddress = servAddr;
  162.     while(serverAddress != NULL)
  163.     {
  164.         serverAddresses.push_back(*serverAddress->ai_addr);
  165.         serverAddress=serverAddress->ai_next;
  166.     }
  167.     freeaddrinfo(servAddr);
  168. }
  169.  
  170. void getLocalAddresses(vector<sockaddr> & localAddresses, ULONG subnet, ULONG subnetMask)
  171. {
  172.     SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
  173.     throwIfError(sd, "Failed to get a socket");
  174.  
  175.     INTERFACE_INFO InterfaceList[20];
  176.     ULONG nBytesReturned;
  177.     int iResult = WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0);
  178.     throwIfError(iResult, "Failed calling WSAIoctl");
  179.  
  180.     int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
  181.     for (int i = 0; i < nNumInterfaces; ++i)
  182.     {
  183.         sockaddr_in *pAddress;
  184.         pAddress = (sockaddr_in *) & (InterfaceList[i].iiAddress);
  185.         if ((pAddress->sin_addr.s_addr & subnetMask) == subnet)
  186.         {
  187.             localAddresses.push_back(*(sockaddr*)&(*pAddress));
  188.         }
  189.     }
  190. }
  191.  
  192.  
  193.  
  194.  
  195. template<class T>
  196. int inline findAndReplace(T& source, const T& find, const T& replace)
  197. {
  198.     int num=0;
  199.     auto fLen = find.size();
  200.     auto rLen = replace.size();
  201.     for (int pos=0; (pos=source.find(find, pos))!=T::npos; pos+=rLen)
  202.     {
  203.         num++;
  204.         source.replace(pos, fLen, replace);
  205.     }
  206.     return num;
  207. }
  208.  
  209. void throwIfError(int result, string msg)
  210. { if(result == SOCKET_ERROR) { throw WSAException(msg); }; }
  211. void throwIfError(WSAException ex)
  212. { if(ex.errorCode()) { throw ex; }; }
  213. std::ostream& operator<<(std::ostream& os, const sockaddr_in& addr)
  214. { os << inet_ntoa(addr.sin_addr) << ":" << htons(addr.sin_port); return os; }
  215. std::ostream& operator<<(std::ostream& os, const sockaddr& addr)
  216. { return operator<<(os, *reinterpret_cast<sockaddr_in const *>(&addr)); }
  217.  
  218. WSAException::WSAException(string message)
  219. {
  220.     _errorCode = WSAGetLastError();
  221.  
  222.     LPSTR errorString = NULL;
  223.     FormatMessageA(
  224.         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  225.         0, _errorCode, 0, (LPSTR)&errorString, 0, 0);
  226.  
  227.     _fullMessage = "ERROR: ";
  228.     _fullMessage += message;
  229.     _fullMessage += "   WSAError (";
  230.     _fullMessage += std::to_string(static_cast<long long>(_errorCode));
  231.     _fullMessage += ") ";
  232.     _fullMessage += errorString;
  233.  
  234.     LocalFree(errorString);
  235. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement