Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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
Sockets 使用curllib向服务器发送数据_Sockets_Http_Curl_Tcp_Client - Fatal编程技术网

Sockets 使用curllib向服务器发送数据

Sockets 使用curllib向服务器发送数据,sockets,http,curl,tcp,client,Sockets,Http,Curl,Tcp,Client,我对所有这些http东西都很陌生,我正在尝试与服务器进行通信 我需要编写发送到服务器的客户端-我知道服务器返回什么,但不确定如何发送数据: 我(客户端)使用HTTP将XML(二进制格式)发布到服务器的url:192.168.2.111/senddata(即Post/senddata) 服务器响应为: TCP: [ACK] Seq=1274 Ack=504 Win=525088 Len=0 也就是说,问题出在这里——服务器没有使用HTTP应答进行应答。 协议服务器在我发送后使用的XML是TCP,

我对所有这些http东西都很陌生,我正在尝试与服务器进行通信

我需要编写发送到服务器的客户端-我知道服务器返回什么,但不确定如何发送数据:

  • 我(客户端)使用HTTP将XML(二进制格式)发布到服务器的url:
    192.168.2.111/senddata
    (即Post/senddata)

  • 服务器响应为:

    TCP: [ACK] Seq=1274 Ack=504 Win=525088 Len=0
    
    也就是说,问题出在这里——服务器没有使用HTTP应答进行应答。 协议服务器在我发送后使用的XML是TCP,这使得
    curl\u易于执行
    不回来

  • 在步骤2中服务器TCP应答之后,I-客户端应使用HTTP延续或非HTTP通信以循环方式向服务器发送二进制数据

  • 服务器异步性与

    TCP: [ACK] Seq=1274 Ack=3424 Win=522176 Len=0
    
    对于每个二进制数据发送

  • 因此,为了在步骤1中发送XML,我使用

    curl_easy_setopt(mCurlHndl, CURLOPT_URL, "192.168.2.111");
    curl_easy_setopt(mCurlHndl, CURLOPT_CUSTOMREQUEST, "POST /senddata");
    curl_easy_setopt(mCurlHndl, CURLOPT_POST, 1L);
    curl_easy_setopt(mCurlHndl, CURLOPT_POSTFIELDS, sXML.c_str());
    curl_easy_setopt(mCurlHndl, CURLOPT_POSTFIELDSIZE, sXML.length());
    
    headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
    headers = curl_slist_append(headers, "Accept:");
    headers = curl_slist_append(headers, (string("Content-Length: ") + string(to_string(sXML.length()))).c_str());
    curl_easy_setopt(mCurlHndl, CURLOPT_HTTPHEADER, headers);
    
    res = curl_easy_perform(mCurlHndl);
    
    服务器不发送回复:

    TCP: [ACK] Seq=1274 Ack=504 Win=525088 Len=0
    
    (当然,仅限于其他seq/ack/win编号)

    好的,问题开始了

    a
    curl\u easy\u perform
    不会返回,因为(我认为)服务器回复不是HTTP,而是TCP

    b。好吧,假设我可以绕过它,给出超时

        curl_easy_setopt(mCurlHndl, CURLOPT_TIMEOUT_MS, 1000);
    
    但我只知道我做错了什么

    c。假设我给出了超时时间,现在在步骤3中,我需要使用HTTP延续或非HTTP通信发送循环数据流

    我不知道如何做到这一点,因为它不应该是正常的职位一样,在第1步。 它应该是HTTP延续或非HTTP通信

    很抱歉我的解释不好,但这也是我在HTTP方面的一点经验造成的

    似乎在第1步之后,服务器破坏了正常的http连接规则,我需要发送循环中的二进制数据,但同样,我不知道如何执行第2步和第3步。例如,如何使用curllib从服务器获取TCP ACK,我将知道如何移动到步骤3,以及如何(步骤3)通过相同的连接(我认为)将循环中的二进制数据发送到服务器


    我想补充一点,服务器返回应该返回的内容。在步骤2中,服务器应该返回TCP:[ACK]Seq=1274 ACK=504 Win=525088 Len=0,因为这是服务器应该做的-这就是服务器协议。这并不是说我没有正确地发送它(在步骤1中),这就是为什么它发送TCP应答而不是http

    以下是Wireshark日志: 192.168.2.7是客户(有效)。 192.168.2.111是服务器。 在第一行(seq 9)中,clinet post二进制xml(post/senddata),然后二进制数据流发送循环开始,如您所见:

    9   0.173574000 192.168.2.7     192.168.2.111   HTTP    380     POST /senddata HTTP/1.1  (application/octet-stream)
    10  0.176611000 192.168.2.111   192.168.2.7     TCP     60      4089 > 53419 [ACK] Seq=1274 Ack=504 Win=525088 Len=0
    11  0.182581000 192.168.2.111   192.168.2.7     UDP     90      Source port: 4020  Destination port: 4005
    12  0.553367000 192.168.2.7     192.168.2.111   HTTP    1354    Continuation or non-HTTP traffic
    13  0.553403000 192.168.2.7     192.168.2.111   HTTP    1354    Continuation or non-HTTP traffic
    14  0.555539000 192.168.2.111   192.168.2.7     TCP     60      4089 > 53419 [ACK] Seq=1274 Ack=3424 Win=522176 Len=0
    15  0.555698000 192.168.2.7     192.168.2.111   HTTP    1354    Continuation or non-HTTP traffic
    16  0.555724000 192.168.2.7     192.168.2.111   HTTP    1354    Continuation or non-HTTP traffic
    17  0.555724000 192.168.2.7     192.168.2.111   HTTP    1354    Continuation or non-HTTP traffic
    18  0.555724000 192.168.2.7     192.168.2.111   HTTP    1354    Continuation or non-HTTP traffic
    19  0.558870000 192.168.2.111   192.168.2.7     TCP     60      4089 > 53419 [ACK] Seq=1274 Ack=6344 Win=519248 Len=0
    20  0.559033000 192.168.2.7     192.168.2.111   HTTP    1354    Continuation or non-HTTP traffic
    
    ..... and many other sends like seq 12 - seq 20 ........
    
    我如何用curllib做这样的事情-这是我的问题


    再次感谢

    您没有正确使用curl发送HTTP
    POST
    请求。请尝试以下方法:

    curl_easy_setopt(mCurlHndl, CURLOPT_URL, "http://192.168.2.111/senddata");
    curl_easy_setopt(mCurlHndl, CURLOPT_POST, 1L);
    curl_easy_setopt(mCurlHndl, CURLOPT_POSTFIELDS, sXML.c_str());
    curl_easy_setopt(mCurlHndl, CURLOPT_POSTFIELDSIZE, sXML.length());
    
    struct curl_slist *headers = curl_slist_append(NULL, "Content-Type: application/octet-stream");
    headers = curl_slist_append(headers, "Accept:");
    curl_easy_setopt(mCurlHndl, CURLOPT_HTTPHEADER, headers);
    
    res = curl_easy_perform(mCurlHndl);
    curl_slist_free_all(headers);
    
    // process reply using curl_easy_getinfo() and curl_easy_recv() as needed...
    
    话虽如此,您确定应该将
    内容类型
    作为
    应用程序/octet流
    发送吗?通常,XML是使用
    text/XML
    application/XML
    或其他与XML相关的
    内容类型发布的,因此服务器知道它正在处理XML数据<代码>应用程序/八位字节流
    指的是不知道实际类型的任意二进制数据

    另外,将
    Accept
    标题设置为空值基本上意味着您不接受任何回复数据。除非您只希望接受特定的
    内容类型
    回复类型,或者希望接受服务器想要发送的任何数据,否则您应该省略
    接受
    标题

    阅读HTTTP协议的正式定义及其工作原理

    更新:由于您显然是在处理自定义协议而非标准HTTP,因此无法使用
    curl\u easy\u perform()
    发送HTTP请求。您必须启用
    CURLOPT\u CONNECT\u ONLY
    选项,以便
    curl\u easy\u perform()
    只打开套接字连接,然后使用
    curl\u easy\u send()
    发送实际请求和后续二进制数据,例如:

    CURLcode curl_send(CURL *curl, const void * buffer, size_t buflen)
    {
        size_t sent;
    
        uint8_t *pbuf = (uint8_t*) buffer;
        while (buflen > 0)
        {
            do
            {
                res = curl_easy_send(curl, pbuf, buflen, &sent); 
            }
            while (res == CURLE_AGAIN);
    
            if (res != CURLE_OK)
                return res;
    
            pbuf += sent;
            buflen -= sent;
        }
        while (buflen > 0);
    
        return CURLE_OK;
    } 
    


    嗨,雷米。在您的回答中,您将重点放在了4个步骤中的步骤1上,但正如您所解释的,步骤1没有问题。是的,我需要应用程序/八位字节流,因为我以二进制格式发送XML。如上所述,步骤1没有问题。是的,我可以使用curl_easy_setopt(mCurlHndl,CURLOPT_URL,”)来执行步骤1,但这两个步骤都给出了相同的结果-这一步没有问题。我需要步骤2-4的帮助。再次感谢您的回答。我想补充一点,服务器返回应该返回的内容。在步骤2中,服务器应该返回TCP:[ACK]Seq=1274 Ack=504 Win=525088 Len=0,因为这是服务器应该做的-这是服务器协议。并不是我没有正确发送它(在步骤1中)这就是它发送TCP应答而不是http的原因。还有一件事,Remy,即使有了您的答案,curl_easy_perform仍然不会返回,因为server by designed没有使用http头进行应答,而是按照书面形式发送TCP ack应答。您关注的是TCP包头,而不是TCP有效负载数据。两件事是不同的。http服务器将不发送0字节TCP数据包来答复HTTP请求。实际的答复数据包将包含HTTP答复有效负载。您正在查看TCP对发送到服务器的TCP数据包的确认。这些数据包与包含服务器对HTTP请求的实际答复的TCP数据包不同。您需要注意数据包payloads,而不是数据包头。如果您使用WireShark,请使用其“跟随TCP流”“只查看有效负载数据的选项。嗨,雷米。是的,我使用WireShark。特定的服务器会这样做。正如您在Follow TCP流中所说的,我看到与该服务器一起工作的其他客户机执行我编写的操作。所以,为了继续您编写的内容,客户端似乎发送了http post请求,而服务器从未使用http应答进行响应。客户端在循环中不断发送其他二进制数据。该数据由客户端(如WireShark中所示)使用HTTP协议和I
    mCurlHndl = curl_easy_init();
    
    ...
    
    curl_easy_setopt(mCurlHndl, CURLOPT_URL, "http://192.168.2.111");
    curl_easy_setopt(mCurlHndl, CURLOPT_CONNECT_ONLY, 1);
    
    res = curl_easy_perform(mCurlHndl);
    if (res == CURLE_OK)
    {
        string req =
            "POST /senddata HTTP/1.1\r\n"
            "Content-Type: application/octet-stream\r\n"
            "Content-Length: " + to_string(sXML.length()) + "\r\n"
            "\r\n"
            + sXML;
    
        res = curl_send(mCurlHndl, req.c_str(), req.length());
        if (res !- CURLE_OK) ...
    
        res = curl_send(mCurlHndl, ...binary data...);
        if (res !- CURLE_OK) ...
    
        res = curl_send(mCurlHndl, ...binary data...);
        if (res !- CURLE_OK) ...
    
        res = curl_send(mCurlHndl, ...binary data...);
        if (res !- CURLE_OK) ...
        ...
    }
    
    ...
    
    curl_easy_cleanup(mCurlHndl);