Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ SSL_WRITE在通过TCP为TLS以不同功能发送时合并消息_C++_Ssl_Openssl_Tls1.2_Winsock2 - Fatal编程技术网

C++ SSL_WRITE在通过TCP为TLS以不同功能发送时合并消息

C++ SSL_WRITE在通过TCP为TLS以不同功能发送时合并消息,c++,ssl,openssl,tls1.2,winsock2,C++,Ssl,Openssl,Tls1.2,Winsock2,我正在编写一个客户端来向远程服务器发送数据。我使用SSL\u WRITE发送了3条不同的消息(hello,hello1,hello2),但在服务器中我只能看到这样发送的一条消息:hellohello1hello2。 有人能帮助我吗?我在这里遗漏了什么?为什么不发送单独的hello、hello1和hello2消息,而是发送一个字符串hellohello1hello2。 我是openSSL新手,你能推荐一些教程来学习TCP上TLS的openSSL吗。我需要使用TCP上的TLS将日志从客户端计算机发送

我正在编写一个客户端来向远程服务器发送数据。我使用
SSL\u WRITE
发送了3条不同的消息(hello,hello1,hello2),但在服务器中我只能看到这样发送的一条消息:
hellohello1hello2
。 有人能帮助我吗?我在这里遗漏了什么?为什么不发送单独的hello、hello1和hello2消息,而是发送一个字符串hellohello1hello2。 我是openSSL新手,你能推荐一些教程来学习TCP上TLS的openSSL吗。我需要使用TCP上的TLS将日志从客户端计算机发送到远程syslog服务器

#include <winsock2.h>
#include <ws2tcpip.h>
#include <Wspiapi.h>  // This is for pre XP machines to work with new APIs. See MSDN

#include "openssl/sha.h"
#include "openssl/rsa.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/x509v3.h"
#include "openssl/rand.h"
#include "openssl/crypto.h"
#include <errno.h>
#include <iostream>

#include <thread>
using namespace std;
#include <string>

SSL_CTX *InitSSL_CTX(void)
{
    
    const SSL_METHOD *method = TLSv1_2_method(); // Create new client-method instance 
    SSL_CTX *ctx = SSL_CTX_new(method);


    // Trusted root CA certificate bundle
    int iRetVal = SSL_CTX_load_verify_locations(ctx, "ca.pem", NULL);
    if (iRetVal != ERR_LIB_NONE)
    {
        cout<<"Failed to load trusted CA certificates bundle";
        exit(EXIT_FAILURE);
    }

// Callback gets invoked for each certificate in the certificate chain; we just log certificate information in there

    if (ctx == nullptr)
    {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
    return ctx;
}


int OpenConnection(const char *hostname, const char *port)
{
    SOCKET ConnectSocket;
    struct addrinfo *result, *ptr, hints;
    int iResult;
    char portStr[1024];


/*
Initialize Winsock.
WSAStartup allows to specify what version of WinSock you want to use.
It sets up all the "behind the scenes stuff" that any process needs to use sockets.
winSockDLL is loaded into the process and it sets up many internal structures.
Each process must call WSAStartup to initialize the structures within its own memory space and WSACleanup to tear them down again when it is finished using sockets.
*/
    WSADATA wsaData;
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        cout << "WSAStartup failed with error: " << iResult << endl;
        return 1;
    }


    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(hostname, port, &hints, &result);
    if (iResult != 0)
    {
        cout << "getaddrinfo failed with error: " << iResult;
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
    {
        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
        ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET)
        {
            cout << "socket failed with error: " << WSAGetLastError();
            break;
        }

        // Connect to server.
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            cout << "connect failed" << endl;
            continue;
        }
        break;
    }

    freeaddrinfo(result);
    if (ConnectSocket == INVALID_SOCKET) {
        cout << "Unable to connect to server!" << endl;
        WSACleanup();
        return 1;
    }
    return ConnectSocket;
}

int main()
{
     SSL_CTX *ctx = InitSSL_CTX();
     SSL *ssl = SSL_new(ctx);
     if (ssl == nullptr)
     {
       cout << "SSL_new() failed\n";
       exit(EXIT_FAILURE);
     }

     //Host is hardcoded to localhost for testing purposes
     const int sfd = OpenConnection("172.16.74.4", "6514");
     SSL_set_fd(ssl, sfd);
 
     const int status = SSL_connect(ssl);
     if (status != 1)
     {
         SSL_get_error(ssl, status);
         ERR_print_errors_fp(stderr); //High probability this doesn't do anything
         cout << "SSL_connect failed with SSL_get_error code :" << status << endl;
         exit(EXIT_FAILURE);
     }

     cout << "Connected with %s encryption\n" << SSL_get_cipher(ssl) << endl;
     DisplayCerts(ssl);

      SSL_write(ssl, "hello", strlen("hello"));
      SSL_write(ssl, "hello1", strlen("hello1"));
      SSL_write(ssl, "hello2", strlen("hello2"));

      SSL_free(ssl);

      SSL_CTX_free(ctx);

      return 0;
#包括
#包括
#include//这是用于XP之前的计算机与新API一起工作。见MSDN
#包括“openssl/sha.h”
#包括“openssl/rsa.h”
#包括“openssl/ssl.h”
#包括“openssl/err.h”
#包括“openssl/x509v3.h”
#包括“openssl/rand.h”
#包括“openssl/crypto.h”
#包括
#包括
#包括
使用名称空间std;
#包括
SSL_CTX*初始化SSL_CTX(无效)
{
const SSL_METHOD*METHOD=TLSv1_2_METHOD();//创建新的客户端方法实例
SSL_CTX*CTX=SSL_CTX_新(方法);
//受信任的根CA证书束
int iRetVal=SSL\u CTX\u加载\u验证\u位置(CTX,“ca.pem”,NULL);
如果(iRetVal!=无错误)
{

这不是tcp的工作原理,没有单独的消息,只是一个连续的字节流,你需要添加你自己的消息分隔符。我应该如何在这里添加我自己的消息分隔符@AlanBirtles你能帮忙吗?在消息之间添加逗号?@aromahola:这个网站上有许多类似的问题。典型的方法是使用固定大小的长度参数作为消息前缀,或在消息之间有一个清晰的分隔符。第一种方法通常更容易实现,因为它可以预先明确获得长度需要多少字节,以及从长度中获得以下消息需要多少字节。分隔符需要您连续分析格式化读取的数据,也可能在正常数据中转义分隔符。@aromahola:除此之外:SSL\u write通常写入不同的SSL记录,这些记录在服务器上应该是可分离的。如果不可分离,则问题可能是服务器端代码(未显示)的方式正在读取数据。不过,您最好不要依赖SSL记录设置的消息边界,因为SSL记录的最大大小可能小于您的消息的最大大小-在这种情况下,它将被拆分为多个记录,并且您再次面临一个问题,即不清楚消息的结束位置。