ilostmyid2 Ответов: 0

981019 - принимать функция ждет, пока пакет был отправлен


Привет Есть источник (камера), который отправляет уведомления (сигналы тревоги движения) на порт 8085 сервера, на который я подписался по его IP-адресу. Может быть, в таких переговорах я не могу назвать его "сервером", но это наш сервер, который обслуживает некоторые другие вещи.
I've written two programs for receiving and echoing current motion status, for now only on screen. Packets which are received are in shape of XML which I may parse and find the required info. For testing, I just extract times which are labeled UtcTime. Another machine subscribed itself to the same camera by using Onvif Device Manager, so that I may check whether I miss some 'times'. One of these programs are in GoLang and one is in C++. The former one works as expected while the latter one doesn't. Maybe this one (C++) has been my first experience in socket programming. I didn't use any additional library while in C++ and I used the traditional socket programming method not to be required to use any additional library at customer site too. The problem is that ODM echos new times (or say notification messages) as well as the GoLang code while the C++ code sticks at accept function (accepting... message). I give you both for investigation.

Записи:

1. Примите функциональные палочки, и я завершу программу с помощью Ctrl+C. В следующий раз, когда я запускаю программу (C++) Я получаю пакеты, которые не мог получить раньше!
2. ОС-это Linux (Ubuntu 12.04). Код GoLang работает в той же операционной системе.

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];
        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;
}


Что я уже пробовал:

Во-первых, я подумал, что это может быть потому, что я не получаю весь блок с помощью одной функции recv. Для этого я выделил блок 80K, чтобы быть достаточно большим, чтобы вместить все полученное уведомление. Но его поведение не изменилось. Тогда я подумал, что это может быть потому, что я вызываю recv в основном потоке, пока другие уведомления готовы, и в то время, когда я должен их обработать, я иду к recv предыдущему. Для этого я переместил recv в отдельный процесс (с помощью вилки), но это не помогло.

Richard MacCutchan

Вам нужно будет использовать свой отладчик, чтобы выяснить, почему accept никогда не активируется, когда клиент отправляет ему сообщение.

ilostmyid2

для отладки внутрь принимать ассемблерный код?!

Richard MacCutchan

Отладки на уровне исходного кода обычно достаточно. Но только вы можете создать точную среду, в которой выполняется этот код, поэтому только вы можете выполнить отладку.

ilostmyid2

Понятия не иметь. Код находится перед вами. Он просто прилипает к accept. Что я могу сделать? Приведенный выше код работает без каких-либо проблем. Что отлаживать?!

Richard MacCutchan

Да, код передо мной, но он ничего мне не говорит. Как я уже говорил, мы не можем отладить этот код, потому что у нас нет среды для его тестирования.

0 Ответов