Parsing a url into host and path I have a program which splits a url into host and path:

int main(int argc, char** argv){
  std::vector&lt;std::string&gt; url = parseUrl(argv[1]);

  memset(&amp;hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  int MAXDATASIZE = 1024;
  std::string request = &quot;GET &quot; +url.at(1) + &quot; HTTP/1.1\r\n\r\n&quot;;
  const char* charRequest = request.c_str();
  char buf[MAXDATASIZE];
  if((status = getaddrinfo(url.at(0).c_str(), &quot;80&quot;, &amp;hints, &amp;servinfo)) != 0){
    std::cout &lt;&lt; &quot;getaddrinfo: &quot; &lt;&lt; gai_strerror(status) &lt;&lt; &quot;\n&quot;;
    return 2;
  } else {
    std::cout &lt;&lt; &quot;Server struct created successfully\n&quot;;
  }
  if((sock = socket(servinfo-&gt;ai_family, servinfo-&gt;ai_socktype, servinfo-&gt;ai_protocol)) == -1){
    std::cout &lt;&lt; &quot;Error creating socket\n&quot;;
    return 2;
  } else {
    std::cout &lt;&lt; &quot;Successfully created socket\n&quot;;
  }
  if(connect(sock, servinfo-&gt;ai_addr, servinfo-&gt;ai_addrlen) == -1){
    std::cout &lt;&lt; &quot;Error connecting to host &quot; &lt;&lt; url.at(0) &lt;&lt; &quot; at port &quot; &lt;&lt; &quot;80&quot; &lt;&lt; &quot;\n&quot;;
    return 2;
  } else {
      std::cout &lt;&lt; &quot;Connected successfully to &quot; &lt;&lt; url.at(0) &lt;&lt; &quot;at port &quot; &lt;&lt; &quot;80&quot; &lt;&lt; &quot;\n&quot;;
  }
  if((send(sock, charRequest, strlen(charRequest), 0)) == -1){
     std::cout &lt;&lt; &quot;Error communicating with website\n&quot;;
     return 2;
  } else {
     std::cout &lt;&lt; &quot;Sent request successfully to &quot; &lt;&lt; url.at(0) &lt;&lt; &quot; at port &quot; &lt;&lt; &quot;80&quot; &lt;&lt; &quot;\n&quot;;
  }
  if(recv(sock, buf, MAXDATASIZE, 0) == -1){
     std::cout &lt;&lt; &quot;Error recciving data from &quot; &lt;&lt; url.at(0) &lt;&lt; &quot; at port &quot; &lt;&lt; &quot;80&quot; &lt;&lt; &quot;\n&quot;;
  } else {
    std::cout &lt;&lt; &quot;Recieved data successfully from &quot; &lt;&lt; url.at(0) &lt;&lt; &quot; at port &quot; &lt;&lt; &quot;80&quot; &lt;&lt; &quot;\n&quot;;
  }
  std::ofstream file;
  file.open(argv[2]);
  file &lt;&lt; buf;
  file.close();
  close(sock);

  freeaddrinfo(servinfo);
}

 // Returns vector with host as first argument and path as second
  std::vector&lt;std::string&gt; parseUrl(std::string url){
    std::vector&lt;std::string&gt; ret;
    size_t dotPos = url.find('.');
    size_t slashPos = url.find('/', dotPos);
    std::string host = url.substr(0, slashPos);
    std::string path = url.substr(slashPos, url.length());
    ret.push_back(host);
    ret.push_back(path);
    return ret;
  }

Does anyone have suggestions for improvement. Especially about the clunky vector return?
Rather than using a std::vector and using the indices to specify the host and path, we can create a little struct and refer to the members by name:
struct URL
{
  std::string host;
  std::string path;
};

So we can refer to url.host instead of url.at(0).

As pointed out in the comments, the parsing method could be more accurate and comprehensive. It's fine to only support a small subset of the url syntax, but we should at least check that we got what we expected in the string.
In this case, I think we should:

Throw an error if we don't find a dot.
Either throw an error if we don't find a slash, OR set the path part of the url to &quot;/&quot; to ensure that our GET request is valid.


int MAXDATASIZE = 1024;
...
char buf[MAXDATASIZE];

This doesn't compile for me. MAXDATASIZE must be a constant.
We can remove the need for a separate constant by using std::array:
std::array&lt;char, 1024&gt; buf;
// now we can use buf.size() :)


Even for something small like this, it's probably worth writing our own socket class. This provides some cleanup safety (RAII), as well as making the code in main() a lot simpler and easier to read by removing some of details of the network code. e.g. something like the following:
struct socket
{
public:

    socket();
    explicit socket(struct addrinfo const&amp; address);

    socket(socket const&amp;) = delete;
    socket&amp; operator=(socket const&amp;) = delete;

    socket(socket&amp;&amp; other);
    socket&amp; operator=(socket&amp;&amp; other);

    ~socket();

    std::size_t send(char const* data, std::size_t data_size);
    std::size_t receive(char* buffer, std::size_t buffer_size);

    bool is_open() const;
    void close();

private:

    SOCKET m_handle;
};

We could also move the address lookup out of main() into a separate function, and keep the addrinfo in a unique pointer with a custom deleter that calls freeaddrinfo(). Something like:
std::unique_ptr&lt;addrinfo, std::function&lt;void(addrinfo*)&gt;&gt; lookup_address(std::string const&amp; node, std::string const&amp; service, int ai_family, int ai_socktype, int ai_protocol, int ai_flags = 0)
{
  auto ai_hints = addrinfo();
  // ... set up hints!

  auto output = (addrinfo*) nullptr;
  auto result = getaddrinfo(node.c_str(), service.c_str(), &amp;ai_hints, &amp;output);
  // ... check errors!

  return { output, [] (addrinfo* ai) { freeaddrinfo(ai); } };
}

So we might end up a main like:
int main(int argc, char** argv)
{
  if (argc != 3)
    throw std::runtime_error(&quot;Unexpected argument count!&quot;);

  auto url = parse_url(argv[1]);
  auto address = lookup_address(url.host, &quot;80&quot;, AF_UNSPEC, SOCK_STREAM, 0, 0);
  
  if (!address)
    throw std::runtime_error(&quot;Failed address lookup!&quot;);

  auto s = socket(*address);
  
  if (!s.is_open())
    throw std::runtime_error(&quot;Failed to connect!&quot;);
  
  auto request = &quot;GET &quot; + url.path + &quot; HTTP/1.1\r\n\r\n&quot;;
  auto sent = s.send(request.c_str(), request.size() + 1);

  if (sent != request.size() + 1)
    throw std::runtime_error(&quot;Failed to send request!&quot;);

  auto buffer = std::array&lt;char, 1024&gt;();
  auto received = s.receive(buffer.data(), buffer.size());

  if (received == 0)
    throw std::runtime_error(&quot;No data received!&quot;);

  std::ofstream(argv[2]).write(buffer.data(), received);
}

(code not compiled or tested).