0

Hi I am new in Socket Programming and try to create a client server applciation using in which my server is Camera and client in my C++ application. When I see the packet transfer between computer and camera it showing that camera is sending more than 150000 packets after that it stops. But when I am receving that I am able to receive 400 - 450 packets at a time after that the recvfrom function goes to waiting state. and If I again run that exe file without stopping the previous one it again receive 400-450 packets.

Code for Receving 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;
        }
    }

I am running the .exe with the administrator rights.

So can anyone please tell me why the recvfrom function is going in waiting state.

Thanks in Advance.

EDIT:-

Sorry that I am providing the whole code.

  #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
}

In the above code I have to first send this 59 commands written in _packetConfig function then only camera will send Image packets I am receiving the reply of all that commands.

When I run wireshark also with that code I can see that after these 59 commands the camera is giving 3580*51 packets.i.e 51 frames and each frame contain 3580 packets

  • What is in `errno` after `recvfrom` fails? Also, why create the socket as `SOCK_RAW`? I think you want `SOCK_DGRAM`. – Paul Sanders Jun 25 '18 at 17:14
  • I am not getting error or not the else part is printing the code just stuck at recvfrom function after receiving 400-450 packets – Chandrapal Singh Jhala Jun 25 '18 at 17:54
  • No if I use SOCK_DGRAM I can't get the packet I don't know why as I said earlier I have not much idea about the sockets. – Chandrapal Singh Jhala Jun 25 '18 at 17:54
  • Please show the sending code (all of it). Thx. – Paul Sanders Jun 25 '18 at 17:55
  • Should I show the whole code? – Chandrapal Singh Jhala Jun 25 '18 at 17:56
  • Is there a lot of it? What I actually want to see how the socket is created and the code that calls `sendto()`. – Paul Sanders Jun 25 '18 at 18:04
  • Oh sorry for that. the sendto function is called from _packetConfig which is called from main(). – Chandrapal Singh Jhala Jun 25 '18 at 18:05
  • And both the sockets are created in main – Chandrapal Singh Jhala Jun 25 '18 at 18:06
  • @ChandrapalSinghJhala You **absolutely** should be using `SOCK_DGRAM` on both ends, since you are using the UDP protocol. The ONLY time you should EVER use `SOCK_RAW` is when you want to implement a *custom* network protocol, or promiscuously capture all network packets (neither of which are necessary in this situation). `SOCK_DGRAM` is the preferred socket type for UDP. Whatever notions you have about using `SOCK_RAW` are wrong. [I tried to explain that to you earlier](https://stackoverflow.com/questions/50999531/raw-sockets-in-c-windows/50999582#comment89000249_50999582). – Remy Lebeau Jun 25 '18 at 20:09
  • @ChandrapalSinghJhala Can you provide the Wireshark capture? Or at least a screenshot of a *complete* packet (or at least the packet headers before the image data) from the camera? – Remy Lebeau Jun 26 '18 at 23:27
  • @ChandrapalSinghJhala where? – Remy Lebeau Jul 02 '18 at 15:07

1 Answers1

2

Thank you for posting your code. There are actually a few things wrong with it so first I will post some code that works as a reference and then mention the major issues I noticed with yours afterwards.

OK, here is some code that works for me:

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

To run this in 'send' mode, specify send as the first argument on the command line. Otherwise it acts as a receiver (aka server).

So what's wrong with your code? Well, in no particular order:

  • as we already said, you shouldn't be using SOCK_RAW
  • you need to call bind on the receiving socket so that it knows what port to listen on. The sockaddr *from parameter to recvfrom doesn't mean what you think it means (please check the docs). You will see I pass this as NULL.
  • you were misinterpreting the return value from WSAStartup. Again, please check the docs.

But having said all that, it was essentially the call to bind that you were missing. I rewrote the code because yours is rather messy.

Also, important detail, UDP doesn't guarantee delivery - there are a number of reasons why a packet that has been sent does not get received or might even get received out of sequence (does your camera sequence the packets in some way?)
You need to cater for that in the logic of your application (and it that's a problem, it's better to use TCP, which does guarantee packet delivery and sequencing).

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • Thank you Sir, It is working with SOCK_DGRAM and the system is capturing all the image packet but when I print anything inside recvfrom function then I think it miss to print the statement for all the packet receive. – Chandrapal Singh Jhala Jul 02 '18 at 06:31
  • Yes, it probably will. If the sender sends packets faster than the receiver can read them then some will get quietly dropped _because UDP doesn't guarantee delivery_. You should most likely actually be using TCP here, unless there's a _very_ good reason not to. – Paul Sanders Jul 02 '18 at 07:09
  • But the Camera is using UDP protocol. Is their any way so that I can receive all of them? – Chandrapal Singh Jhala Jul 02 '18 at 07:16
  • @ChandrapalSinghJhala use `setsockopt()` to increase the size of the socket's receive buffer. And make sure you are not wasting time processing packets between receives. Read as fast as possible, usually by reading and queuing packets in one thread and processing them in another thread. – Remy Lebeau Jul 02 '18 at 15:06
  • @Chandra This sounds like a good idea. Sorry, I forgot you were streaming from a camera. I have added it my answer (and got rid of `errno` - use `WSAGetLastError()` instead). – Paul Sanders Jul 02 '18 at 17:22
  • @RemyLabeau and PaulSanders Thank you sir for your guidance – Chandrapal Singh Jhala Jul 03 '18 at 04:10
  • You're welcome, good call by @Remy. I added a note to my answer about packets being received out of sequence which you should at least be aware of. It's unlikely to happen on a LAN, but across a wider area network it might very well happen. – Paul Sanders Jul 03 '18 at 05:08