在Windows上使用C++本地发送POST请求

huangapple go评论165阅读模式
英文:

Sending a POST request locally in C++ on Windows

问题

我有一个在同一台电脑上(Windows 10)运行的C++客户端和Golang服务器,并且我希望客户端向服务器发送POST请求。我想要发送的请求是/test。两个项目都可以编译和运行,但是客户端没有处理这些请求,即使服务器显示

"HTTP-GA-SERVER: POST Successfully sent"

以下是C++代码:

#include <winsock2.h>
#include "ga-http-post.h"

int sendPostToMushroom(HttpRequestType req, void* metrics)
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
        std::cout << "WSAStartup failed." << std::endl;
        return 1;
    }
    SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    SOCKADDR_IN SockAddr;
    SockAddr.sin_port=htons(8080);
    SockAddr.sin_family=AF_INET;
    SockAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    std::cout << "HTTP-GA: Connecting..." << std::endl;

    if (Socket < 0) {
        std::cout << "HTTP-GA: Error creating socket: " << WSAGetLastError() << std::endl;
        return 1;
    }

    if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){
        std::cout << "HTTP-GA: Error connecting: " << WSAGetLastError() << std::endl;
        return 1;
    }
    std::cout << "HTTP-GA: Connected to " << inet_ntoa(SockAddr.sin_addr) << std::endl;

    char buffer[2048];
    strcpy(buffer,"POST /test HTTP/1.1\n");

    if (send(Socket,buffer, strlen(buffer),0) != strlen(buffer))
    {
        std::cout << "HTTP-GA: Error sending:" << WSAGetLastError() << std::endl;
        return 1;
    }
    closesocket(Socket);
    WSACleanup();
    std::cout << "HTTP-GA: POST Successfully sent" << std::endl;
    return 0;
}

以下是Golang代码:

func (a *Agent) runGaHTTPHandler() {
    fmt.Println("HTTP : Init HTTP Server")

    http.HandleFunc("/ready", a.handleServerReady)
    http.HandleFunc("/unavailable", a.handleServerUnavailable)
    http.HandleFunc("/connected", a.handleClientConnected)
    http.HandleFunc("/disconnected", a.handleServerUnavailable)
    http.HandleFunc("/MetricsCollected", a.handleMetrics)
    http.HandleFunc("/test", a.handleTest)

    fmt.Println("HTTP : Listen and serve")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func (a *Agent) handleTest(w http.ResponseWriter, r *http.Request) {
    fmt.Print("HTTP : Test successful\n")
}

编辑:C++代码已更改,仍然无法正常工作。

英文:

I have a c++ client and and golang server on the same pc (on windows 10), and I want the client to send POST requests to the server. The request I want to send is the /test one. Both projects compile and run well, but the requests are not handled by the client, even if the server is showing

&quot;HTTP-GA-SERVER: POST Successfully sent&quot;

Here is the C++ code :

#include &lt;winsock2.h&gt;
#include &quot;ga-http-post.h&quot;

int sendPostToMushroom(HttpRequestType req, void* metrics)
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &amp;wsaData) != 0) {
        std::cout &lt;&lt; &quot;WSAStartup failed.&quot; &lt;&lt; std::endl;
        return 1;
    }
    SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    SOCKADDR_IN SockAddr;
    SockAddr.sin_port=htons(8080);
    SockAddr.sin_family=AF_INET;
    SockAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    std::cout &lt;&lt; &quot;HTTP-GA: Connecting...&quot; &lt;&lt; std::endl;

    if (Socket &lt; 0) {
        std::cout &lt;&lt; &quot;HTTP-GA: Error creating socket: &quot; &lt;&lt; WSAGetLastError() &lt;&lt; std::endl;
        return 1;
    }
  
    if(connect(Socket,(SOCKADDR*)(&amp;SockAddr),sizeof(SockAddr)) != 0){
        std::cout &lt;&lt; &quot;HTTP-GA: Error connecting: &quot; &lt;&lt; WSAGetLastError() &lt;&lt; std::endl;
        return 1;
    }
    std::cout &lt;&lt; &quot;HTTP-GA: Connected to &quot; &lt;&lt; inet_ntoa(SockAddr.sin_addr) &lt;&lt; std::endl;

    char buffer[2048];
    strcpy(buffer,&quot;POST /test HTTP/1.1\n&quot;);

    if (send(Socket,buffer, strlen(buffer),0) != strlen(buffer))
    {
        std::cout &lt;&lt; &quot;HTTP-GA: Error sending:&quot; &lt;&lt; WSAGetLastError() &lt;&lt; std::endl;
        return 1;
    }
    closesocket(Socket);
    WSACleanup();
    std::cout &lt;&lt; &quot;HTTP-GA: POST Successfully sent&quot; &lt;&lt; std::endl;
    return 0;
}

And the golang code :

func (a *Agent) runGaHTTPHandler() {
    fmt.Println(&quot;HTTP : Init HTTP Server&quot;)

    http.HandleFunc(&quot;/ready&quot;, a.handleServerReady)
    http.HandleFunc(&quot;/unavailable&quot;, a.handleServerUnavailable)
    http.HandleFunc(&quot;/connected&quot;, a.handleClientConnected)
    http.HandleFunc(&quot;/disconnected&quot;, a.handleServerUnavailable)
    http.HandleFunc(&quot;/MetricsCollected&quot;, a.handleMetrics)
    http.HandleFunc(&quot;/test&quot;, a.handleTest)

    fmt.Println(&quot;HTTP : Listen and serve&quot;)
    log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))
}

func (a *Agent) handleTest(w http.ResponseWriter, r *http.Request) {
    fmt.Print(&quot;HTTP : Test successful\n&quot;)
}

EDIT : C++ code changed, still not working

答案1

得分: 1

编辑 <BR>
在客户端代码中,尝试更改:
strcpy(buffer,"POST /test HTTP/1.1\n");

strcpy(buffer,"POST /test HTTP/1.1\r\nHost: localhost\r\n\r\n");

HTTP/1.1要求存在Host HTTP头;在头部之后,应该有一个额外的换行符(\r\n)。当然,如果需要的话,将localhost更改为实际的主机名。

[关于Go http服务器代码的先前回答]<BR>
handleTest函数中,你需要向http.ResponseWriter w写入或使用其WriteHeaderWrite函数。目前,你的代码中的fmt.Print很可能会在你启动Go服务器的终端中打印字符串,但不会将其发送到客户端。尝试以下(简化的)版本的Go程序:

package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/test", handleTest)

    fmt.Println("HTTP : Listen and serve")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func handleTest(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("HTTP : Test successful\n"))
}

当你启动Go服务器时,客户端应该得到一个类似于使用curl完成的响应(你也可以通过浏览器访问进行测试):
<pre>
$ curl http://localhost:8080/test
HTTP : Test successful
</pre>

你可以在net/http包的文档中查看ResponseWriterWriteWriteHeader函数的描述:https://golang.org/pkg/net/http/#ResponseWriter

英文:

Edit <BR>
In the client code, try to change:
strcpy(buffer,&quot;POST /test HTTP/1.1\n&quot;);
to
strcpy(buffer,&quot;POST /test HTTP/1.1\r\nHost: localhost\r\n\r\n&quot;);

HTTP/1.1 requires the presence of the Host HTTP header; after the headers, there should be an extra newline (\r\n). Of course, change localhost to the actual hostname if needed.

[Previous answer regarding the Go http server code]<BR>
In the handleTest function, you need to write to the http.ResponseWriter w or use its WriteHeader and Write functions. Currently fmt.Print in your code most likely prints the string in the terminal where you started the Go server but does not send it to the client. Try the following (simplified) version of your Go program:

package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
)

func main() {
	http.HandleFunc(&quot;/test&quot;, handleTest)

	fmt.Println(&quot;HTTP : Listen and serve&quot;)
	log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))
}

func handleTest(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(&quot;HTTP : Test successful\n&quot;))
}

When you started the Go server, the client should get a response like this one done with curl (you can also access it through a browser for testing) :
<pre>
$ curl http://localhost:8080/test
HTTP : Test successful
</pre>

You can see the description of the ResponseHeader's Write and WriteHeader functiosn in the documentation for the net/http package: https://golang.org/pkg/net/http/#ResponseWriter

huangapple
  • 本文由 发表于 2016年7月26日 22:14:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/38592320.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定