C++ 接收函数在数据包被发送时等待

C++ 接收函数在数据包被发送时等待,c++,linux,sockets,go,camera,C++,Linux,Sockets,Go,Camera,有一个源摄像头,它向我为其订阅IP的服务器的8085端口发送运动警报通知。也许在这样的谈判中,我不能称之为“服务器”,但它是我们的服务器,提供其他服务。 我已经写了两个程序来接收和回显当前的运动状态,现在只在屏幕上。接收到的数据包是XML格式的,我可以对其进行解析并找到所需的信息。对于测试,我只提取标记为UtcTime的时间。另一台机器使用Onvif设备管理器订阅了同一台相机,这样我就可以检查我是否错过了一些“时间”。这些程序中的一个在GoLang,一个是C++。前者的工作原理与预期相符,而后者

有一个源摄像头,它向我为其订阅IP的服务器的8085端口发送运动警报通知。也许在这样的谈判中,我不能称之为“服务器”,但它是我们的服务器,提供其他服务。 我已经写了两个程序来接收和回显当前的运动状态,现在只在屏幕上。接收到的数据包是XML格式的,我可以对其进行解析并找到所需的信息。对于测试,我只提取标记为UtcTime的时间。另一台机器使用Onvif设备管理器订阅了同一台相机,这样我就可以检查我是否错过了一些“时间”。这些程序中的一个在GoLang,一个是C++。前者的工作原理与预期相符,而后者则不然。也许这一个C++是我第一次在Socket编程中体验。我在C++中没有使用任何额外的库,我使用了传统的套接字编程方法,不需要在客户站点使用任何额外的库。问题是ODM在接受C++功能时接受新的消息或通知消息,以及Galang-Cal码。消息我给你们两个调查

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "strings"
)

func count() (f func() int) {
    var counter int
    f = func() int {
        counter++
        return counter
    }
    return
}

func main() {
    http.HandleFunc("/", Server)
    http.ListenAndServe(":8085", nil)
}

func Server(w http.ResponseWriter, r *http.Request) {
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        log.Fatal(err)
    }
    str := string(body)
    for {
        index := strings.Index(str, "UtcTime")
        if index == -1 {
            break
        }
        part := str[index+20 : index+28]
        fmt.Printf("%s\n", part)
        str = str[index+28:]
    }
}
这是GoLang中正常工作的代码。现在C++代码没有按预期工作,坚持接受:

#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string>

#define DBG printf("%s:%d\n", __FILE__, __LINE__)
#define DIE die(__FILE__, __LINE__)

void die(const char *file, int line)
{
    printf("%s:%d: %s\n", file, line, strerror(errno));
    exit(1);
}

std::string extractTime(const char *utc)
{
    char buf[80];
    memcpy(buf, utc + 11, 8);
    buf[9] = 0;
    return buf;
}

int main()
{
    printf("creating socket...\n");
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
        DIE;
    int reuseaddr = 1;
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) == -1)
        DIE;

    printf("binding...\n");
    sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8085);
    addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(sock, (sockaddr *)&addr, sizeof(addr)) == -1)
        DIE;

    printf("listening...\n");
    if (listen(sock, SOMAXCONN) == -1)
        DIE;
    socklen_t size = sizeof(addr);
    while (true)
    {
        printf("accepting...\n");
        int new_sock = accept(sock, 0, 0);
        if (new_sock < 0)
            DIE;
        const int buf_size = 80;
        char buf[buf_size * 2 + 1];
        memset(buf, 0, buf_size);
        int read_size;
        std::string time;
        while (true)
        {
            memcpy(buf, buf + buf_size, buf_size);
            read_size = recv(new_sock, buf + buf_size, buf_size, 0);
            if (read_size < 0)
                DIE;
            buf[buf_size + read_size] = 0;
            char *p = strstr(buf, "UtcTime");
            if (p && (p - buf < buf_size))
            {
                char buf2[80];
                char *p2 = strstr(p + 9, "\"");
                if (p2)
                {
                    memcpy(buf2, p + 9, p2 - p - 9);
                    buf2[p2 - p - 9] = 0;
                    time = extractTime(buf2);
                    printf("%s\n", time.c_str());
                }
            }
            if (strstr(buf, "</SOAP-ENV:Envelope>"))
                break;
        }
    }
    return 0;
}
虽然这段代码也不能像预期的那样工作,但我可以找到一些线索。你看我把端口改成了8081。这是因为8085已经满了!这就是我的结论,你应该确认我是否正确。第一次,当我运行程序时,我得到了以下输出:

2919 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
5395 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
7871 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
13408 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
16503 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
18979 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
21455 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
23931 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
26407 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
28883 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
31359 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33835 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
43739 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
45260 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
45260 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
42340 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
太好了!似乎Receive没有读出并没有转移它得到的东西。收到的数据包将在下次我再次呼叫Receive时保留在那里。第三次读取新收到的数据包以及两个旧数据包!缓冲区大小逐渐增大,直到足够大。在此之后,尺寸仍然很高,但每次都可能减小或增大!直到我再也没有新的包裹了。Accept不返回,端口已满且无用。如果我再次运行该程序,我将不再得到任何答案,它将停留在AcceptSocket,或者整个缓冲区立即被接受,对AcceptSocket的第二次调用将停留。
因此,乍一看,我可能会说,问题似乎是由接收到的数据包没有被recv释放引起的。我认为C++程序也会发生同样的情况。但是GoLang密码呢?我认为它可能是因为缓冲区的大小不限于C++或C代码。如果我让它运行,系统内存可能会满。缓冲区的大小可能是障碍物。不管怎样,假设我的假设是正确的,我能怎么想?我的代码中有什么问题没有导致缓冲区释放?我能做什么?

你的C++变体有一些有趣的缺点:

初始化buf的前80个buf_大小字符,然后从未初始化的下80个memcpy读取第一个memcpy。 无论缓冲区的后半部分中实际有多少有用/初始化的字节,都可以将80个字节从缓冲区的后半部分存储到前半部分。 您调用accept一次,以获取连接的套接字,然后读取直到出错并退出。这将破坏侦听套接字,而其余的连接将不被接受。如果EOF read_size为0,则可能永远旋转而不退出,因为将来的每次读取也将返回0。 如果在缓冲区中的任意位置找到字符串UtcTime,则会搜索从9字节后开始出现的双引号,即使UtcTime距离缓冲区末尾的距离小于9字节。
我怀疑如果你解决了所有这些问题,事情可能会更好。通常,服务器应该分离一个线程或进程来处理每个新的传入连接,并让主线程/进程返回到accept以等待其他套接字。在Go中编写代码要容易得多,因为它内置了所有正确的东西来完成这项工作。

使用strace来验证您声称的声明是真实的,并且这将阻止您接受。所显示的代码可能没有实际执行您认为它正在执行的操作。所显示的C++代码有缺陷,导致访问未初始化的内存导致未定义的行为。处理输入缓冲区的逻辑已中断,它将尝试解析未初始化的内存。所有这些缓冲区诡计的目的都有点不清楚,似乎没有任何有用的用途[@SamVarshavchik:我不知道strace,但是当我把printf放在accept之后,它没有打印任何东西,这意味着它被卡在accept中,不是吗?关于未初始化的缓冲区,你是对的,我更新了代码。但它肯定不会改变代码的行为。处理输入缓冲区的逻辑不是解析一个坏的n字符串,但它不是完全可用的。这很清楚,而且是一个很好的机制。@yaodav:链接似乎断了。这里什么也没说!@hamidi try Now谢谢你的回答。1.你被操纵了
关于读取未初始化的缓冲区。我初始化了第一个部分,并使用memcpy将未初始化的部分复制到它上面。我更改了代码以初始化整个缓冲区。2.这似乎是一个愚蠢的副本,但它不会引起任何问题。第二部分包括以\0结尾的读取缓冲区。因此,strstr可以正常工作,即使先前读取的其他字符也可以复制。3.我将代码更改为在单独的进程中调用recv,但它没有更改行为。因为问题不是由调用下一个AcceptAddition时的延迟引起的,所以我将代码更改为检查read_size,如果它等于零,它将离开循环。4.如果UtcTime的格式为…,相机每次都会发送UtcTime,那么为什么我不应该指望它呢?在U.I更新问题以包含这些更改后,引号始终为8个字符。您可能收到的数据包少于整个数据包。您正在使用的Go例程io.ReadAll将整个输入读取到缓冲区中,而不是尝试使用滑动窗口;这可能是一个更好的策略。在读取整个缓冲区之前,将调用recv。这应该会导致同样的结果。2.我也用了这个策略。使用了足够大的缓冲区80K,得到了相同的结果。这段代码中的其他部分工作不正常,这似乎隐藏在我们的视线之外。也许值得将其分解为更可测试的部分。让家长做倾听和接受;像现在这样分叉,让子对象读取EOF并将数据保存到一个普通文件中,然后在更新的代码中退出一个小错误:您应该退出,这样子对象就不会尝试接受—尽管这实际上应该是可行的。然后,尝试针对普通文件提取时间代码,而不是针对侦听和接受调用的循环。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace tcplistener
{
    class Program
    {
        static void Main(string[] args)
        {
            const int port = 8081;

            TcpListener tcpListener = new TcpListener(IPAddress.Any, port);
            tcpListener.Start();

            while (true)
            {
                Socket socketConnection = tcpListener.AcceptSocket();
                var buf = new byte[80000];
                var size = socketConnection.Receive(buf);
                Console.WriteLine("{0} bytes received", size);
                Console.WriteLine("{0}", Encoding.UTF8.GetString(buf, 0, size).Substring(0, 80));
                socketConnection.Disconnect(true);
            }
        }
    }
}
2919 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
5395 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
7871 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
13408 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
16503 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
18979 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
21455 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
23931 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
26407 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
28883 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
31359 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33835 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
43739 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
45260 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
36500 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
45260 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
42340 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http
33580 bytes received
POST /behnama-subscription HTTP/1.1
Host: 192.168.14.127:8081
SOAPAction: http