recvfrom принимает только несколько пакетов, после чего переходит в состояние ожидания - PullRequest
0 голосов
/ 25 июня 2018

Привет, я новичок в Socket Programming и пытаюсь создать клиент-серверное приложение, используя в котором мой сервер - Камера и клиент в моем приложении C ++.Когда я вижу передачу пакетов между компьютером и камерой, это показывает, что камера отправляет более 150000 пакетов, после чего останавливается.Но когда я получаю, что я могу получить 400 - 450 packets за один раз после этого, функция recvfrom переходит в состояние ожидания.и если я снова запускаю этот exe-файл, не останавливая предыдущий, он снова получает 400-450 packets.

код для приема пакетов

SOCKET out1 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
    if (out1 == INVALID_SOCKET)
    {
        cout << out1 << endl;
    }
    server.sin_family = AF_INET;
    server.sin_port = htons(3956);
    inet_pton(AF_INET, "192.168.1.140", &server.sin_addr);
    int serverLength = sizeof(server);

    connect(out1, (sockaddr*)&server, serverLength);
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        int bytesIn = recvfrom(out1, buf, 1444, 0, (sockaddr*)&server, &serverLength);
        if (bytesIn > 0)
        {
            cout << "Image Received :" << bytesIn <<packet_counter << endl;
            packet_counter++;
        }
        else
        {
            cout << "Not Received : " << endl;
        }
    }

Я запускаю.exe с правами администратора.

Так может кто-нибудь, пожалуйста, скажите мне, почему функция recvfrom находится в состоянии ожидания.

Заранее спасибо.

РЕДАКТИРОВАТЬ: -

Извините, что я предоставляю весь код.

  #include <stdio.h>
#include <Windows.h>
#include <thread>
#include <WinSock2.h>

// Library
#pragma comment(lib, "ws2_32.lib")

using namespace std;

//***** Function Decleration *****//
void _packetConfig(SOCKET);
void _sendPacket(SOCKET, const char*, int, int);

// Global Variable
sockaddr_in server;

//***** Main Function *****//
void main(char argc, char* argv[])
{
    WSADATA data;
    WORD version = MAKEWORD(2, 2);
    if(WSAStartup(version, &data) == SOCKET_ERROR)
    {
        cout << "Can't Start Socket" << WSAGetLastError<<endl;
        return;
    }
    char buf[2000];

        SOCKET out1 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
        if (out1 == INVALID_SOCKET)
        {
            cout << out1 << endl;
        }
        server.sin_family = AF_INET;
        server.sin_port = htons(3956);
        inet_pton(AF_INET, "192.168.1.140", &server.sin_addr);
        int serverLength = sizeof(server);

        connect(out1, (sockaddr*)&server, serverLength);


        int packet_counter = 0;


        SOCKET out = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

        _packetConfig(out);

        cout << "Inside Main" << endl;
        while (1)
        {
            //connect(out1, (sockaddr*)&server, serverLength);
            memset(buf, 0, sizeof(buf));
            int bytesIn = recvfrom(out1, buf, 1444, 0, (sockaddr*)&server, &serverLength);
            if (bytesIn > 0)
            {
                cout << "Image Received :" << bytesIn <<packet_counter << endl;
                packet_counter++;
            }
            else
            {
                cout << "Not Received : " << endl;
            }
        }

        WSACleanup();
}

//***** Function to Send Bytes to the Camera *****//
void _sendPacket(SOCKET sock, const char* s, int len, int i)
{
    int sendOk = sendto(sock, (const char*)s, len, 0, (sockaddr*)&server, sizeof(server));

    if (sendOk == SOCKET_ERROR)
    {
        cout << "Didn't Work" << WSAGetLastError() << endl;
    }
    else
    {
        cout << "\nSend Succesfully" << " " << i << endl;
    }
    char buf[2000];
    int serverLength = sizeof(server);
    int bytesIn = recvfrom(sock, buf, 2000, 0, (sockaddr*)&server, &serverLength);
    if (bytesIn > 0)
    {
        cout << "Message Received :" << bytesIn << endl;
    }
}

//***** Function to call the _sendPacket function and send commands to the Camera *****//
void _packetConfig(SOCKET sock)
{
    // 59 Commands and every command call _snedPacket function to send commands to camera  it will working properly
}

В приведенном выше коде я должен сначала отправить эту 59 commands, написанную в функции _packetConfig, затем только камераsend Image packets Я получаю ответ на все эти команды.

Когда я запускаю wireshark также с этим кодом, я вижу, что после этих 59 команд камера выдает 3580*51 packages.ie 51 кадр и каждаякадр содержит 3580 пакетов

1 Ответ

0 голосов
/ 26 июня 2018

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

ОК, вот код, который работает для меня:

#include <WinSock2.h>                   // ** before** windows.h
#include <WS2tcpip.h>
#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <assert.h>

#pragma comment (lib, "ws2_32.lib")

const int port = 3956;

// main
int main (char argc, char* argv[])
{
    WSADATA wsadata;
    WORD version = MAKEWORD(2, 2);

    int err = WSAStartup (MAKEWORD (2, 2), &wsadata);
    if (err)
    {
        std::cout << "WSAStartup failed, error: " << err << std::endl;
        return 255;
    }

    char buf [1444];
    bool send = argc > 1 && _stricmp (argv [1], "send") == 0;

    if (send)
    {
        // Send
        SOCKET skt_out = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        assert (skt_out != INVALID_SOCKET);

        sockaddr_in destination_address = { };
        destination_address.sin_family = AF_INET;
        destination_address.sin_port = htons (port);
        inet_pton (AF_INET, "192.168.1.2", &destination_address.sin_addr);
        memset (buf, 'Q', sizeof (buf));
        printf ("Sending: ");

        for ( ; ; )
        {
            sendto (skt_out, buf, sizeof (buf), 0, (const sockaddr *) &destination_address, sizeof (destination_address));
            printf (".");
            Sleep (50);
        }

        closesocket (skt_out);
        WSACleanup ();
        return 0;
    }

    // Receive
    SOCKET skt_in = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    assert (skt_in != INVALID_SOCKET);

    int receive_buffer_size = 65536;
    if ((setsockopt (skt_in, SOL_SOCKET, SO_RCVBUF, (const char *) &receive_buffer_size, sizeof (int)) ) < 0)
        std::cout << "Could not set SO_RCVBUF, error: " << WSAGetLastError () << std::endl;

    sockaddr_in receive_address = { };
    receive_address.sin_family = AF_INET;
    receive_address.sin_port = htons (port);
    receive_address.sin_addr.s_addr = htonl (INADDR_ANY);

    if (bind (skt_in, (const sockaddr *) &receive_address, sizeof (receive_address)) == -1)
    {
        std::cout << "bind failed , error: " << WSAGetLastError () << std::endl;
        return 255;
    }

    int packetCounter = 0;
    printf ("Receiving: ");

    for ( ; ; )
    {
        int bytesIn = recvfrom (skt_in, buf, sizeof (buf), 0, NULL, 0);
        if (bytesIn > 0)
            std::cout << "Packet received:" << bytesIn << " bytes (" << ++packetCounter << ")" << std::endl;
        else
            std::cout << "Receive error: " << WSAGetLastError () << std::endl;
    }

    closesocket (skt_in);
    WSACleanup ();
    return 0;
}

Чтобы запустить это в режиме 'send', укажите send в качестве первого аргумента в командной строке. В противном случае он действует как получатель (он же сервер).

Так что не так с вашим кодом? Ну, без определенного порядка:

  • как мы уже говорили, вы не должны использовать SOCK_RAW
  • вам нужно вызвать bind на принимающем сокете, чтобы он знал, какой порт прослушивать. Параметр sockaddr *from для recvfrom не означает, что вы думаете, что он означает (проверьте документы ). Вы увидите, что я передаю это как NULL.
  • вы неверно истолковали возвращаемое значение из WSAStartup. Опять же, пожалуйста, проверьте документы.

Но, сказав все это, по сути это был призыв к bind, которого вы пропустили Я переписал код, потому что ваш довольно грязный.

Кроме того, важная деталь: UDP не гарантирует доставку - существует ряд причин, по которым отправленный пакет не получен или даже может быть получен не по порядку (ваша камера каким-то образом упорядочивает пакеты ?)
Это необходимо учитывать в логике вашего приложения (и в этом проблема, лучше использовать TCP, который гарантирует доставку пакетов и последовательность).

...