向HTTP服务器发送POST请求时发生Winsock send()错误
Winsock send() error when sending POST request to HTTP server
在发送POST
字符串时,我无法让send()
返回除-1
以外的任何内容:
#include <vector>
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
SOCKET socket_create_http()
{
SOCKET sock;
SOCKADDR_IN SockAddr;
struct hostent* host;
char url[] = "domain.net";
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
host = gethostbyname(url);
SockAddr.sin_port = htons(54000);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
int bound = bind(sock, (SOCKADDR*)(&SockAddr), sizeof(SockAddr));
return(sock);
}
int main()
{
WSADATA ws_data;
WORD ws_version = MAKEWORD(2, 2);
int startup = WSAStartup(ws_version, &ws_data);
SOCKET sock_http = socket_create_http();
string data = "action=0&data=0";
string request_string = "POST ";
request_string += "stuff://domain.net/script.php?";
request_string += " HTTP/1.1rn"; // or HTTP/1.0
request_string += "Host: domain.netrn";
request_string += "Content-Length: " + to_string(data.size()) + "rn";
request_string += "rn";
request_string += data;
int sent = send(sock_http, request_string.c_str(), strlen(request_string.c_str()), 0);
cout << "SENT: " << sent << endl;
closesocket(sock_http);
return 0;
}
我可能需要预处理器定义中的_WINSOCK_DEPRECATED_NO_WARNINGS
来运行它
我已经做了几天了。有没有什么想法我可能会在套接字设置或post格式方面出错,或者两者兼而有之?
更新:我已经更新了代码,现在我在发送POST
字符串时收到400 bad request
:
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
#include <winsock2.h>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
SOCKET sock_http;
SOCKET socket_create_http(const char* hostname, unsigned short port)
{
hostent* host = gethostbyname(hostname);
if (host)
{
cout << "HTTP HOST: " << host << endl;
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock != INVALID_SOCKET)
{
SOCKADDR_IN SockAddr = {};
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(port);
SockAddr.sin_addr.s_addr = *reinterpret_cast<unsigned long*>(host->h_addr);
if (connect(sock, reinterpret_cast<SOCKADDR*>(&SockAddr), sizeof(SockAddr)) != SOCKET_ERROR)
{
cout << "HTTP SOCKET CREATED: " << sock << endl << endl;
return sock;
}
//closesocket(sock); //safety
}
}
}
bool http_post(string data)
{
char bb_receive[4096];
ostringstream request;
request << "POST stuff://domain.net/script.php HTTP/1.1rn"; //stuff is https
request << "Host: domain.netrn";
request << "Content-Length: " << data.size() << "rn";
request << "Content-Type: application/x-www-form-urlencodedrn";
request << "Connection: closern";
request << "rn";
request << data;
string request_string = request.str();
size_t data_size = request_string.size();
const char* pdata = static_cast<const char*>(request_string.c_str());
bool all_sent = false;
while (data_size > 0)
{
int sent = send(sock_http, pdata, data_size, 0);
if (sent == SOCKET_ERROR)
{
cout << "SOCKET FAILED IN SEND LOOP" << endl;
break;
}
pdata += sent;
data_size -= sent;
} //SEND
if (data_size <= 0) { all_sent = true; }
if (all_sent)
{
ZeroMemory(bb_receive, 4096);
int bytes_received = recv(sock_http, bb_receive, 4096, 0);
if (bytes_received > 0)
{
cout << "Bytes received (Socket " << sock_http << "): " << bytes_received << endl;
}
for (int i = 0; i < bytes_received; i++) { cout << bb_receive[i]; }
} //RECEIVE
return all_sent;
}
int main()
{
WSADATA ws_data;
WORD ws_version = MAKEWORD(2, 2);
int startup = WSAStartup(ws_version, &ws_data); if (startup != 0) { cout << "WSA FAILED" << endl; }
sock_http = socket_create_http("domain.net", 443);
bool success = http_post("action=0&data=0");
cout << "WSA Last Error: " << WSAGetLastError() << endl;
closesocket(sock_http);
return 0;
}
以下是recv()
的输出——服务器的响应:
Bytes received (Socket 532): 4096
HTTP/1.1 400 Bad Request
Date: Mon, 15 Aug 2022 18:23:43 GMT
Server: Apache
Upgrade: h2,h2c
Connection: Upgrade, close
Accept-Ranges: bytes
Vary: Accept-Encoding
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Content-Type: text/html
代码的主要问题是您没有调用connect()
函数来建立与HTTP服务器IP/端口的连接。您使用的是bind()
函数,该函数仅建立套接字的本地IP/端口,但不能将套接字bind()
连接到远程IP/端口。这就是connect()
的作用。
当套接字函数失败时,请使用WSAGetLastError()
查找原因。在您的情况下,send()
将失败,并出现WSAENOTCONN
错误:
https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send
返回值
如果没有发生错误,send将返回发送的字节总数,该总数可以小于len参数中请求发送的字节数否则返回值
SOCKET_ERROR
,调用WSAGetLastError
可以检索到特定的错误代码
错误代码 含义 WSAENOTCONN 插座未连接
相关文章:
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- (Winsock) UDP 接收工作正常,但同一套接字的发送失败
- WinSock Non-Blocking I/O
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- 使用 winsock 接收 http 请求
- ZMQ::send() 抛出异常并终止 QNX 进程.为什么以及如何从中恢复?
- 如何查找 winsock.h 在 Visual Studio 中的包含位置
- 在Linux上交叉编译Windows应用程序时如何链接到Winsock?
- 如何为winsock的send()函数构造constchar*缓冲区
- 有没有办法方便地为 Winsock send() 生成 HTTP 标头,而不是手动连接字符串
- C++ Winsock struct send/recv
- Winsock send()总是在服务器中返回错误10057
- WinSock send() 钩子导致访问冲突
- Winsock nonblock send() wait buffer.正确的方法是什么
- Winsock:回显服务器回复两次,当时我刚刚将其编程为执行一次send()调用
- Winsock send() 单字节传输的问题
- 如何在 winsock 中使'send'无阻塞
- Winsock using send() and FD_WRITE
- WinSock 2.2 TCP/IPv4 send()总是返回发送的所有字节
- 使用Winsock的send()/recv()时是否需要确认响应