简体   繁体   中英

UDP communication is not working. Using the WinSock2 library

I wrote two simple programs, both using UDP. One of them sends packets of data and the other receives them.

I ran both of these programs in the following circumstances:

  • The firewall was turned off.
  • I forwarded the corresponding port, even though I tested it on my LAN.

I tested it while using localhost, ran both programs on the same computer. But it does not work.

The sender program:

#include <iostream>

#include <WinSock2.h>
#include <WS2tcpip.h>

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

#define PORT 1243
#define PORTSTR "1243"
#define IPSTR "127.0.0.1"

#define CYCLECOUNT 100

#define MESS "Hello world!"

int main()
{
    /// True if the socket is initialized.
    bool bSockInit = false;

    /// Initialization.
    WSADATA wsaData;
    if (int err; (err = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
    {
        std::cout << "Failed the startup with error: " << err << '\n';
        goto END;
    }

    /// Creating the socket.
    SOCKET sock;
    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
    {
        std::cout << "Failed the socket with error: " << WSAGetLastError() << '\n';
        goto END;
    }
    bSockInit = true;

    /// Creating the address, to which data is sent.
    sockaddr_in remoteAddr;
    ZeroMemory((PVOID) &remoteAddr, sizeof(remoteAddr));

    // Setting the address familiy to ipv4.
    remoteAddr.sin_family = AF_INET;

    // Setting the port in network byte order.
    remoteAddr.sin_port = htons(PORT);

    // Setting the address from a c-style string.
    InetPton(AF_INET, TEXT(IPSTR), (PVOID) &remoteAddr.sin_addr);

    /// Sending the messages.
    while (std::cin.get() == '\n')
    {
        int byteCount = 0;
        for (int i = 0; i < CYCLECOUNT; ++i)
        {
            byteCount += sendto(sock, MESS, sizeof(MESS), 0, (sockaddr*) &remoteAddr, sizeof(remoteAddr));
        }

        /// Print the number of bytes sent.
        std::cout << "Sent " << byteCount << " bytes times to " IPSTR ":" PORTSTR << ".";
    }

END:
    // If the socket was initialized successfully then dispose of it.
    if (bSockInit)
    {
        std::cout << "closesocket finished with code: " << closesocket(sock) << '\n';
    }

    std::cout << "WSACleanup finished with code: " << WSACleanup() << '\n';

    std::cin.get();
    return 0;
}

The receiver program:

#include <iostream>

#include <WinSock2.h>

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

// The port where data is to be received.
#define PORT 1243

int main(int argc, char** argv)
{
    /// True if the socket is initialized.
    bool bSockInit = false;

    /// Initialization.
    WSADATA wsaData;
    if (int err; (err = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
    {
        std::cout << "Failed the startup with error: " << err << '\n';
        goto END;
    }

    /// Creating the socket.
    SOCKET sock;
    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
    {
        std::cout << "Failed the socket with error: " << WSAGetLastError() << '\n';
        goto END;
    }
    bSockInit = true;

    /// Creating the address.
    sockaddr_in thisAddr;
    ZeroMemory((PVOID) &thisAddr, sizeof(thisAddr));

    // Setting the address familiy to ipv4.
    thisAddr.sin_family = AF_INET;

    // Setting the port in network byte order.
    thisAddr.sin_port = htons(PORT);

    // Setting the address to any, so that incoming data, whichever the ipv4-address is, is accepted.
    thisAddr.sin_addr.S_un.S_addr = htonl(ADDR_ANY);

    if (bind(sock, (sockaddr*)&thisAddr, sizeof(thisAddr)) == SOCKET_ERROR)
    {
        std::cout << "Failed the bind with error: " << WSAGetLastError() << '\n';
        goto END;
    }

    // Buffer to store incoming bytes.
    char buf[1024];

    // The number of bytes that were received.
    int len;

    // Data about the sender.
    sockaddr from;
    int fromlen;
    fromlen = 0;
    // ~Data about the sender.

    // Waiting for a message, containing at least one byte to arrive.
    while ((len = recvfrom(sock, buf, sizeof(buf), NULL, &from, &fromlen)) <= 0);

    // Printing the message that was just received and placed into the buffer.
    for (int i = 0; i < len; ++i)
    {
        std::cout << buf[i];
    }

END:
    // If the socket was initialized successfully then dispose of it.
    if (bSockInit)
    {
        std::cout << "closesocket finished with code: " << closesocket(sock) << '\n';
    }

    std::cout << "WSACleanup finished with code: " << WSACleanup() << '\n';

    std::cin.get();
    return 0;
}

If you have some spare time, run both of the programs and see what happens.

To send data with the sender program you you need to press the ENTER/RETURN key.

I would also appreciate examples of such programs that work.

On the sender, you are not doing any error handling on sendto() at all.

On the receiver, your reading loop is not setting fromlen correctly on each call to recvfrom() , which is likely to make recvfrom() fail with a WSAEFAULT error, which you are not handling or reporting. If recvfrom() fails, you get stuck in an endless loop. Also, your std::cout output should be inside the reading loop, writing the data to the console only when recvfrom() is successful. Also, recvfrom() returning 0 is not an error condition, since UDP allows 0-byte messages, unlike TCP.

Try this instead:

#include <iostream>

#include <WinSock2.h>
#include <WS2tcpip.h>

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

#define PORT 1243
#define PORTSTR "1243"
#define IPSTR "127.0.0.1"

#define CYCLECOUNT 100

#define MESS "Hello world!"

int main()
{
    SOCKET sock = INVALID_SOCKET;

    /// Initialization.
    WSADATA wsaData;
    if (int err; (err = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
    {
        std::cerr << "Failed the startup with error: " << err << '\n';
        goto FINISHED;
    }

    /// Creating the socket.
    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
    {
        std::cerr << "Failed the socket with error: " << WSAGetLastError() << '\n';
        goto CLEANUPWSA;
    }

    /// Creating the address, to which data is sent.
    sockaddr_in remoteAddr;
    ZeroMemory(&remoteAddr, sizeof(remoteAddr));

    // Setting the address familiy to ipv4.
    remoteAddr.sin_family = AF_INET;

    // Setting the port in network byte order.
    remoteAddr.sin_port = htons(PORT);

    // Setting the address from a c-style string.
    inet_pton(AF_INET, IPSTR, &remoteAddr.sin_addr);

    /// Sending the messages.
    while (std::cin.get() == '\n')
    {
        int byteCount = 0;
        for (int i = 0; i < CYCLECOUNT; ++i)
        {
            int sent = sendto(sock, MESS, sizeof(MESS), 0, (sockaddr*) &remoteAddr, sizeof(remoteAddr));
            if (sent == SOCKET_ERROR)
            {
                std::cerr << "Failed the send with error: " << WSAGetLastError() << '\n';
                goto CLEANUPSCKT;
            }
            byteCount += sent;
        }

        /// Print the number of bytes sent.
        std::cout << "Sent " << byteCount << " bytes to " << IPSTR << ":" << PORTSTR << ".";
    }

CLEANUPSCKT:
    // If the socket was initialized successfully then dispose of it.
    std::cout << "closesocket finished with code: " << closesocket(sock) << '\n';

CLEANUPWSA:
    std::cout << "WSACleanup finished with code: " << WSACleanup() << '\n';

FINISHED:
    std::cin.get();
    return 0;
}
#include <iostream>

#include <WinSock2.h>

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

// The port where data is to be received.
#define PORT 1243

int main(int argc, char** argv)
{
    SOCKET sock = INVALID_SOCKET;

    /// Initialization.
    WSADATA wsaData;
    if (int err; (err = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
    {
        std::cerr << "Failed the startup with error: " << err << '\n';
        goto FINISHED;
    }

    /// Creating the socket.
    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
    {
        std::cerr << "Failed the socket with error: " << WSAGetLastError() << '\n';
        goto CLEANUPWSA;
    }

    /// Creating the address.
    sockaddr_in thisAddr;
    ZeroMemory(&thisAddr, sizeof(thisAddr));

    // Setting the address familiy to ipv4.
    thisAddr.sin_family = AF_INET;

    // Setting the port in network byte order.
    thisAddr.sin_port = htons(PORT);

    // Setting the address to any, so that incoming data, whichever the ipv4-address is, is accepted.
    thisAddr.sin_addr.s_addr = htonl(ADDR_ANY);

    if (bind(sock, (sockaddr*)&thisAddr, sizeof(thisAddr)) == SOCKET_ERROR)
    {
        std::cerr << "Failed the bind with error: " << WSAGetLastError() << '\n';
        goto CLEANUPSCKT;
    }

    // Buffer to store incoming bytes.
    char buf[1024];

    // The number of bytes that were received.
    int len;

    // Data about the sender.
    sockaddr_in from;
    int fromlen;

    // Waiting for a message, containing at least one byte to arrive.    
    do
    {
        fromlen = sizeof(from);
        len = recvfrom(sock, buf, sizeof(buf), NULL, (sockaddr*)&from, &fromlen);
        if (len == SOCKET_ERROR)
        {
            std::cerr << "Failed the recv with error: " << WSAGetLastError() << '\n';
            goto CLEANUPSCKT;
        }

        std::cout << "Received " << len << " byte(s) from " << inet_ntoa(from.sin_addr.s_addr) << ":" << ntohs(from.sin_port);

        if (len > 0)
        {
            // Printing the message that was just received and placed into the buffer.
            std::cout << ": ";
            std::cout.write(buf, len);
            std::cout << '\n';
            break;
        }

        std::cout << ", still waiting" << '\n';
    }
    while (true);

CLEANUPSCKT:
    // If the socket was initialized successfully then dispose of it.
    std::cout << "closesocket finished with code: " << closesocket(sock) << '\n';

CLEANUPWSA:
    std::cout << "WSACleanup finished with code: " << WSACleanup() << '\n';

FINISHED:
    std::cin.get();
    return 0;
}

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