英文:
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
"HTTP-GA-SERVER: POST Successfully sent"
Here is the C++ code :
#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;
}
And the golang code :
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")
}
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
写入或使用其WriteHeader
和Write
函数。目前,你的代码中的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包的文档中查看ResponseWriter
的Write
和WriteHeader
函数的描述:https://golang.org/pkg/net/http/#ResponseWriter
英文:
Edit <BR>
In the client code, try to change:
strcpy(buffer,"POST /test HTTP/1.1\n");
to
strcpy(buffer,"POST /test HTTP/1.1\r\nHost: localhost\r\n\r\n");
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 (
"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"))
}
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论