简体   繁体   中英

UDP Socket programmaing c++ Recvfrom() function error

I was not able to find what I was doing wrong on the internet.

My problem is that, recvfrom() function seems to remember the last value instead of making new calls and getting my buffer updated.

I've created the same code logic with Python and it works just find but I can't find a way to do the same in C++.

So that's my code :

#define _WINSOCKAPI_
#include <windows.h>
#include <winsock2.h>
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <time.h>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;

int main()
{
    cout << "\t\t--------------UDP Server ---------------" << endl;
    cout << endl;

    WSADATA WinSockData;
    int iWsaStartup, iWsaCleanup;

    SOCKET UDPSocketServer;
    struct sockaddr_in UDPClient;

    char Buffer[200];

    int iBind, iReceiveFrom;

    int iUDPClientLen = sizeof(UDPClient);
    int iCloseSocket;

    int response, offset;
    ULONG cmd = 0;

    iWsaStartup = WSAStartup(MAKEWORD(2, 2), &WinSockData);

    if (iWsaStartup != 0) {
        cout << "WSAStartup Failed" << endl;
    }
    cout << "WSAStartup Success" << endl;

    //Setting Socket connexion information
    UDPClient.sin_family = AF_INET;
    UDPClient.sin_addr.s_addr = htons(INADDR_ANY);
    UDPClient.sin_port = htons(40100);

    //Informations to send to this address
    const char* msg = "///";
    size_t msg_length = sizeof(msg) - 1;
    struct sockaddr_in myaddr;
    memset(&myaddr, 0, sizeof(myaddr));
    myaddr.sin_addr.s_addr = inet_addr("192.128.20.65");
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(40100);

    //Create Socket
    UDPSocketServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (UDPSocketServer == INVALID_SOCKET) {
        cout << "Socket creation failed with error : " << WSAGetLastError() << endl;
        WSACleanup();
        exit(0);
    }
    cout << "Socket creation success" << endl;

    //Binding Socket to INADDR_ANY 0.0.0.0:40100
    iBind = bind(UDPSocketServer, (SOCKADDR*)&UDPClient, sizeof(UDPClient));
    if (iBind == SOCKET_ERROR) {
        cout << "Binding failed with error : " << WSAGetLastError() << endl;
        closesocket(UDPSocketServer);
        WSACleanup();
        exit(0);
    }
    cout << "Binding success" << endl;

    //Make sure the socket is blocking
    if (ioctlsocket(UDPSocketServer, FIONBIO, &cmd) == SOCKET_ERROR) {
        cout << "ioctlsocket failed with error : " << WSAGetLastError() << endl;
    }
    else
        cout << "ioctlsocket success : " << cmd << endl; //Return 0 because it is set for Blocking

    //Send information to 192.128.20.65:40100
    response = sendto(UDPSocketServer, reinterpret_cast<const char*>(msg), msg_length, 0, (sockaddr*)&myaddr, sizeof(myaddr));
    if (response == SOCKET_ERROR) {
        cout << "Send failed with error : " << WSAGetLastError() << endl;
    }
    cout << "Send success : " << response << endl;

    //Wait 4 seconds
    Sleep(4000);

    //Send information to 192.128.20.65:40100
    response = sendto(UDPSocketServer, reinterpret_cast<const char*>(msg), msg_length, 0, (sockaddr*)&myaddr, sizeof(myaddr));
    if (response == SOCKET_ERROR) {
        cout << "Send failed with error : " << WSAGetLastError() << endl;
    }
    cout << "Send success : " << response << endl;

    while (1) {
        //Capture receive data from any address on port 40100
        //This is supose to be a blocking function but it never block after the first return call
        iReceiveFrom = recvfrom(UDPSocketServer, Buffer, sizeof(Buffer) + 1, MSG_PEEK, (SOCKADDR*)&UDPClient, &iUDPClientLen);
        if (iReceiveFrom == SOCKET_ERROR) {
            cout << "Receive failed with error : " << WSAGetLastError() << endl;
        }
        else if (iReceiveFrom != 0) {
            Buffer[iReceiveFrom] = '\0'; //Add end of line to Buffer
            //printf("%.*s\n", iReceiveFrom, Buffer);
            cout << "Receive success : " << Buffer << endl;
        }
    }
    iCloseSocket = closesocket(UDPSocketServer);

    iWsaCleanup = WSACleanup();
    if (iWsaCleanup == SOCKET_ERROR) {
        cout << "WSA Cleanup failed with error : " << WSAGetLastError() << endl;
    }
    cout << "WSA Cleanup success" << endl;

    system("PAUSE");
    return 0;
}

I've created a UDP C++ socket that binds itself to 0.0.0.0:40100 and listens to that port using the function recvfrom() .

The problem is that my recvfrom() function seems to never update or wait for new data. It just sends over the same old data without waiting.

I've tried to add some code that will change all the value of the buffer, but when recvfrom() is called the value recieved is the same as the old one.

From what I've read, recvfrom() function is supposed to be a blocking function, but in my case, it doesn't seems to work.

I've made sure the function was blocking by looking at ioctlsocket() function response; it's set to 0, so it's supposed to block.

I've also tried to create a new socket for my sendTo() function and I got the same result.

Finally, I've also tried to remove the sendTo() functions, but like my code in Python, no data seems to comeback from the socket if I don't send the string in the first place. (Wireshark shows that there's data that is sent to this port at all the time. Without this initialization, I can't get anything to print on my socket).

I find it strange that data is recieved on a certain port on my computer but when bind to that port I can't see this data before sending data to the address that send it in the first place. So I think the problem might happens between the sendTo() call and the recvfrom() .

将MSG_PEEK与recvfrom一起使用不会从传入数据队列中删除数据,下次您调用recvfrom时,该数据仍然存在。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM