Click here to Skip to main content
14,607,232 members

981019 - accept function waits while packet has been sent

ilostmyid2 asked:

Open original thread
Hi There's a source (camera) which sends notifications (motion alarms) to port 8085 of a server I've subscribed its IP for it. Maybe in such a negotiation I can't call it 'server', but it's our server which serves some other things.
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.

Notes:

1. accept function sticks and I terminate the program by Ctrl+C. The next time I run the program (C++) I get the packets I couldn't get before!
2. OS is Linux (Ubuntu 12.04). The GoLang code works in the same OS.

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

This was the code in GoLang which works properly. Now the C++ code which doesn't work as expected and sticks on accepting...:
#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;
}


What I have tried:

First, I thought it might be because I don't receive the whole block by a single recv function. For this, I allocated a 80K block to be large enough to hold the whole received notification. But the behavior didn't change. Then I thought it might be because I call recv in main thread while the other notification messages are ready and in the time I should process them I go to recv the previous one. For this, I moved recv to a separate process (by fork), but it didn't help.
Tags: C++, Go, Linux, sockets, camera

Preview



When answering a question please:
  1. Read the question carefully.
  2. Understand that English isn't everyone's first language so be lenient of bad spelling and grammar.
  3. If a question is poorly phrased then either ask for clarification, ignore it, or edit the question and fix the problem. Insults are not welcome.
  4. Don't tell someone to read the manual. Chances are they have and don't get it. Provide an answer or move on to the next question.
Let's work to help developers, not make them feel stupid.
Please note that all posts will be submitted under the The Code Project Open License (CPOL).




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100