簡體   English   中英

UDP套接字編程C ++ Recvfrom()函數錯誤

[英]UDP Socket programmaing c++ Recvfrom() function error

我無法在互聯網上找到我做錯的事情。

我的問題是, recvfrom()函數似乎會記住最后一個值,而不是進行新的調用並更新緩沖區。

我已經用Python創建了相同的代碼邏輯,但只能找到它,但是我找不到在C ++中做到這一點的方法。

這就是我的代碼:

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

我創建了一個UDP C ++套接字,該套接字將自身綁定到0.0.0.0:40100並使用函數recvfrom()偵聽該端口。

問題是我的recvfrom()函數似乎從不更新或等待新數據。 它只是發送相同的舊數據而無需等待。

我嘗試添加一些代碼來更改緩沖區的所有值,但是當調用recvfrom()時,接收到的值與舊代碼相同。

根據我的閱讀, recvfrom()函數應該是一個阻塞函數,但就我而言,它似乎不起作用。

我通過查看ioctlsocket()函數響應來確保該函數被阻止; 它設置為0,因此應該阻止。

我也嘗試為sendTo()函數創建一個新的套接字,並且得到了相同的結果。

最后,我也嘗試刪除sendTo()函數,但是就像我在Python中的代碼一樣,如果我不首先發送字符串,似乎沒有數據從套接字返回。 (Wireshark顯示始終有數據發送到此端口。如果沒有進行初始化,則無法在套接字上打印任何內容)。

我發現在計算機的某個端口上接收到數據很奇怪,但是當綁定到該端口時,在將數據發送到首先發送該數據的地址之前,我看不到該數據。 所以我認為問題可能發生在sendTo()調用和recvfrom()

將MSG_PEEK與recvfrom一起使用不會從傳入數據隊列中刪除數據,下次您調用recvfrom時,該數據仍然存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM