C++ MSVC中的TLS客户端++;对于localhost:Port
我有一个本地服务器,它在运行REST API,我可以向其发送以下Curl请求:C++ MSVC中的TLS客户端++;对于localhost:Port,c++,json,visual-studio,sockets,winsock2,C++,Json,Visual Studio,Sockets,Winsock2,我有一个本地服务器,它在运行REST API,我可以向其发送以下Curl请求: curl -X POST "https://localhost:61000/users/logout" -H "accept: */*" -H "Locale: en" 它会给我以下的回应 在MSVC++中,使用WinSock和OpenSSL库,我可以从google.com的端口443获取响应代码200,但当我尝试在端口61000的本地主机时,我总是收到HTTP/1.1400错误请求 // Client int
curl -X POST "https://localhost:61000/users/logout" -H "accept: */*" -H "Locale: en"
它会给我以下的回应
在MSVC++中,使用WinSock
和OpenSSL
库,我可以从google.com
的端口443
获取响应代码200
,但当我尝试在端口61000的本地主机时,我总是收到HTTP/1.1400错误请求
// Client
int main(int argc, char* argv[])
{
WSADATA wsadata;
if ((WSAStartup(MAKEWORD(2, 0), &wsadata)) == 0) {
cout << "-WSAStartup Initialized." << endl;
struct addrinfo hints, * res;
int sockfd;
memset(&hints, 0, sizeof hints);
hints.ai_socktype = 0;// SOCK_STREAM;
hints.ai_protocol = 0;// IPPROTO_TCP;
hints.ai_family = AF_UNSPEC;
if (getaddrinfo("localhost", "61000", &hints, &res) != 0) {
cout << "-getaddrinfo unsuccessful." << WSAGetLastError() << endl;
}
if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == INVALID_SOCKET) {
cout << "-Unable to create socket." << WSAGetLastError() << endl;
}
if ((connect(sockfd, res->ai_addr, res->ai_addrlen)) != SOCKET_ERROR) {
cout << "-Connection Established." << endl;
}
cout << "-Client connected to: " << res->ai_addr << endl;
SSL_library_init();
SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
const SSL_METHOD* meth = TLSv1_2_client_method();
SSL_CTX* ctx = SSL_CTX_new(meth);
ssl = SSL_new(ctx);
if (!ssl) {
printf("Error creating SSL.\n");
log_ssl();
return -1;
}
sock = SSL_get_fd(ssl);
SSL_set_fd(ssl, sockfd);
int err = SSL_connect(ssl);
if (err <= 0) {
printf("Error creating SSL connection. err=%x\n", err);
log_ssl();
fflush(stdout);
return -1;
}
printf("SSL connection using %s\n", SSL_get_cipher(ssl));
const char* request = "GET /users HTTPS/1.1\r\n\r\n";
//SendPacket
int len = SSL_write(ssl, request, strlen(request));
if (len < 0) {
int err = SSL_get_error(ssl, len);
switch (err) {
case SSL_ERROR_WANT_WRITE:
return 0;
case SSL_ERROR_WANT_READ:
return 0;
case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
default:
return -1;
}
}
//RecvPacket
len = 100;
char buf[20000];
do {
len = SSL_read(ssl, buf, 100);
buf[len] = 0;
printf(buf);
} while (len > 0);
if (len < 0) {
int err = SSL_get_error(ssl, len);
if (err == SSL_ERROR_WANT_READ)
return 0;
if (err == SSL_ERROR_WANT_WRITE)
return 0;
if (err == SSL_ERROR_ZERO_RETURN || err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL)
return -1;
}
}
else {
cout << "-WSAStartup Initialization failed." << endl;
if (WSACleanup() != 0) {
cout << "-WSACleanup Successful." << endl;
}
else {
cout << "-WSACleanup Failed." << endl;
}
}
return 0;
}
//客户端
int main(int argc,char*argv[])
{
WSADATA WSADATA;
if((WSAStartup(MAKEWORD(2,0),&wsadata))==0){
cout Https是加密的协议,请先尝试使用http。也就是说,启动不安全的服务器(使用未加密的连接)。或者您可以尝试使用支持https连接的库。实际上,单独编写https协议实现非常困难,许多由专业人员编写的库都尝试过,但都失败了。此外,您使用的getaddrinfo()
是错误的。不要在主机名上包含https://
前缀,这就是它失败的原因。只需自己传入localhost
主机名即可。此外,您的POST
请求的格式稍有错误。“charset=utf-8”
不是有效的HTTP头。charset
是内容类型
头的属性:内容类型:application/json;charset=utf-8“
。您也没有考虑send()
和recv()
可能无法一次性写入/读取所有请求的字节,您需要在实际写入/接收所有预期字节之前以循环方式调用它们。getaddrinfo()
与localhost
一起工作,这是我问题的第2点,我已经尝试了send()
和recv()
在一个循环中,但结果总是一样的。我知道内容类型
标题格式不正确,但更改它们并不会对recv()
@OmChoudharygetaddrinfo()
的奇怪输出产生任何影响。它只适用于主机名,如“localhost”
,不适用于url,如"https://localhost“
。这就是我之前的评论所指出的。斯密森已经解释了为什么你从recv()中得到垃圾
-您没有考虑HTTPS使用的SSL/TLS,您正在发送错误的SSL/TLS握手并返回SSL/TLS错误。请改用未加密的HTTP,或者实现SSL/TLS部分,例如使用OpenSSL库或Microsoft的SChannel API。或者,放弃此代码,改用libCurl或Microsoft的WinInet/WinHT总磷API@RemyLebeau:我已经更新了代码,现在我正在使用OpenSSL
库,它适用于google.com
端口443
,但不适用于localhost:port