C++ MSVC中的TLS客户端++;对于localhost:Port

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

我有一个本地服务器,它在运行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 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()
@OmChoudhary
getaddrinfo()
的奇怪输出产生任何影响。它只适用于主机名,如
“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