c++ - sdl_net udp 服务器设置

标签 c++ sdl-net

我已经查看了有关如何执行此操作的教程和许多其他地方,但是我仍然无法使其正常工作。有趣的是,我确实找到了一个关于如何设置 UDP 聊天程序的教程(我从中派生了这段代码),这对于一个基本示例来说非常棒。

然而,只要我进行非本地测试(我将客户端应该连接的服务器的 IP 从本地主机切换到我的真实 IP),数据包就不会被接收到。我忍不住觉得我把这段代码的服务器部分设置错了。

这就是我目前所拥有的。

Network.h//UDP网络代码。

#pragma once

#include "include/SDL2/SDL_net.h"
#include <cstring>

#include <iostream>
#include <fstream>
#include <sstream>

/*******************************************************************************************
Some things to note about the UDPConnection class.

Init this on both the client and/or server's excutable.  No extra work required. Unless your
planning on tracking the activity and data between multiple clients (eg: for multiplayer).
At which point you just memorize and communicate between different ip's manually.
HINT: look at packet->ip;

*******************************************************************************************/

class UDPConnection
{
    bool quit;
    UDPsocket ourSocket;
    IPaddress serverIP;
public:
    UDPpacket *packet;

    UDPConnection()
    {
        quit = false;
    }
    ~UDPConnection()
    {
        SDLNet_FreePacket(packet);
        SDLNet_Quit();
    }
    bool Init(const std::string &ip, int32_t remotePort, int32_t localPort)
    {
        std::cout << "Connecting to \n\tIP : " << ip << "\n\tPort : " << remotePort << std::endl;
        std::cout << "Local port : " << localPort << "\n\n";

        // Initialize SDL_net
        if (!InitSDL_Net())
            return false;

        if (!OpenPort(localPort))
            return false;

        if (!SetIPAndPort(ip, remotePort))
            return false;

        if (!CreatePacket(65536))
            return false;

        /* bind server address to channel 0 */
        if (SDLNet_UDP_Bind(ourSocket, 0, &serverIP) == -1)
        {
            printf("SDLNet_UDP_Bind: %s\n", SDLNet_GetError());
            return false;
        }

        return true;
    }
    bool InitServer(int32_t remotePort, int32_t localPort) {
        std::cout << "connecting to port" << remotePort << std::endl;
        std::cout << "Local port : " << localPort << "\n\n";

        // Initialize SDL_net
        if (!InitSDL_Net())
            return false;

        if (!OpenPort(localPort))
            return false;

        if (!SetPort(remotePort))
            return false;

        if (!CreatePacket(65536))
            return false;

        SDLNet_UDP_Unbind(ourSocket, 0);

        return true;
    }
    bool InitSDL_Net()
    {
        std::cout << "Initializing SDL_net...\n";

        if (SDLNet_Init() == -1)
        {
            std::cout << "\tSDLNet_Init failed : " << SDLNet_GetError() << std::endl;
            return false;
        }

        std::cout << "\tSuccess!\n\n";
        return true;
    }
    bool CreatePacket(int32_t packetSize)
    {
        std::cout << "Creating packet with size " << packetSize << "...\n";

        // Allocate memory for the packet
        packet = SDLNet_AllocPacket(packetSize);

        if (packet == nullptr)
        {
            std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl;
            return false;
        }

        // Set the destination host and port
        // We got these from calling SetIPAndPort()
        packet->address.host = serverIP.host;
        packet->address.port = serverIP.port;

        std::cout << "\tSuccess!\n\n";
        return true;
    }
    bool OpenPort(int32_t port)
    {
        std::cout << "Opening port " << port << "...\n";

        // Sets our sovket with our local port
        ourSocket = SDLNet_UDP_Open(port);

        if (ourSocket == nullptr)
        {
            std::cout << "\tSDLNet_UDP_Open failed : " << SDLNet_GetError() << std::endl;
            return false;
        }

        std::cout << "\tSuccess!\n\n";
        return true;
    }
    bool SetIPAndPort(const std::string &ip, uint16_t port)
    {
        std::cout << "Setting IP ( " << ip << " ) " << "and port ( " << port << " )\n";

        // Set IP and port number with correct endianess
        if (SDLNet_ResolveHost(&serverIP, ip.c_str(), port) == -1)
        {
            std::cout << "\tSDLNet_ResolveHost failed : " << SDLNet_GetError() << std::endl;
            return false;
        }

        std::cout << "\tSuccess!\n\n";
        return true;
    }
    bool SetPort(uint16_t port)
    {
        std::cout << "Setting up port ( " << port << " )\n";

        // Set IP and port number with correct endianess
//IS THE ISSUE HERE?
        if (SDLNet_ResolveHost(&serverIP, NULL, port) == -1)
        {
            std::cout << "\tSDLNet_ResolveHost failed : " << SDLNet_GetError() << std::endl;
            return false;
        }

        std::cout << "\tSuccess!\n\n";
        return true;
    }
    // Send data. 
    bool Send(const std::string &str)
    {
        // Set the data
        // UDPPacket::data is an Uint8, which is similar to char*
        // This means we can't set it directly.
        //
        // std::stringstreams let us add any data to it using << ( like std::cout ) 
        // We can extract any data from a std::stringstream using >> ( like std::cin )
        //
        //str

        memcpy(packet->data, str.c_str(), str.length());
        packet->len = str.length();

        // Send
        // SDLNet_UDP_Send returns number of packets sent. 0 means error
        //packet->channel = -1;
        if (SDLNet_UDP_Send(ourSocket, -1, packet) == 0)
        {
            std::cout << "\tSDLNet_UDP_Send failed : " << SDLNet_GetError() << "\n"
                << "==========================================================================================================\n";
            //msg.resize(0);
            return false;
        }
        std::cout << "sent to: " << packet->address.host << "\n";
        std::cout << "length is: " << packet->len << "\n";
    }
    inline UDPpacket* recievedData(){
        // Check to see if there is a packet wauting for us...
        if (SDLNet_UDP_Recv(ourSocket, packet))
        {
            /*for (int i = packet->len; i < 512; i++) {
                //may only be needed for local testing.
                packet->data[i] = 0;
            }*/
            //std::cout << "\tData received : " << packet->data << "\n";
            return packet;
        }return NULL;
    }
    inline bool WasQuit()
    {
        return quit;
    }
};

clientSend.cpp//我们客户端的exe。

#include "Network.h"
#include "Graphics.h"
#include <cstdlib>

UDPConnection *udpConnection;

using namespace std;

#define DISPLAY_STRING_ROWS 20
char displayString[DISPLAY_STRING_ROWS][256];

int main(int argc, char **argv){
    setup(120, 120, 600, 400);  //Inits SDL.

    std::string IP = "72.49.67.66";
    int32_t remotePort = 333;
    int32_t localPort = 222;
    udpConnection = new UDPConnection();

    udpConnection->Init(IP, remotePort, localPort);

    UDPpacket *packet;

    for (int i = 0; i < DISPLAY_STRING_ROWS; i++) {
        for (int j = 0; j < 256; j++) {
            displayString[i][j] = 0;
        }
    }

    while (!udpConnection->WasQuit()){
        clear();
        packet = udpConnection->recievedData();
        #define PACKET_LEN packet->len
        #define PACKET_DATA packet->data

        static int currentRow = 0;

        if (packet != NULL) {
            for (int i = 0; i < PACKET_LEN; i++) {
                displayString[currentRow][i] = udpConnection->packet->data[i];
            }
            displayString[currentRow][PACKET_LEN] = 0;
            if (currentRow >= DISPLAY_STRING_ROWS) {
                currentRow = 0;
            }
            else {
                currentRow++;
            }
        }
        for (int i = 0; i < currentRow; i++) {
            if (displayString[i][0] != 0) {
                text(displayString[i], 20, 20, PACKET_LEN * 16, 16, 0, 0, 0);
            }
        }
        render();
        std::string send;
        getline(cin, send);
        udpConnection->Send(send);
    }
    endGame();
}



void displayText() {

}

server.cpp//服务器的exe.

#include "Network.h"
#include "Graphics.h"
#include <cstdlib>

//Right now i'm just assuming that the ip is givin every time it's sent to client/server.

UDPConnection *udpConnection;

using namespace std;

int main(int argc, char* args[]) {
    //std::string IP = "0.0.0.0";  //Not necessary.
    int32_t remotePort = 222;
    int32_t localPort = 333;
    udpConnection = new UDPConnection();

    udpConnection->InitServer(remotePort, localPort);

    UDPpacket *packet;

    setup(120, 120, 600, 400);  //Inits SDL.

    char c[10][80000];
    int cCount = 0;
    int cLength[10];


    bool running = true;  //Is our game loop running?

    while (running) {  //--GAME LOOP!--//
        clear();  //Clears garbage form SDL.

        packet = udpConnection->recievedData();
        #define PACKET_LEN packet->len
        //#define PACKET_DATA packet->data

        if (packet != NULL) {
            cout << "we got a message" << endl;
            packet->data[PACKET_LEN] = 0;
            for (int i = 0; i <= PACKET_LEN; i++) {
                c[cCount][i] = packet->data[i];
            }
            //*c[cCount] = udpConnection->packet->data;
            cLength[cCount] = PACKET_LEN;
            if (cCount == 9) {
                cCount = 0;
            }else{
                cCount++;
            }
        }

        for (int i = 0; i < cCount; i++) {
            text(c[i], 20, i*16, cLength[i] * 16, 16, 0, 0, 0);
        }

        render();  //Causes SDL to draw what we made to our window.
    }
    endGame();  //Necessary to properly shutdown SDL.
}

我希望我不必包含 graphic.c 和 graphics.h 文件,但是如果有必要,请询问,我会将整个项目发布到 repo 上供任何人引用。不过,我希望答案非常简单,我只是一直浏览了一下。

这是我从中获取代码的教程的链接。 http://headerphile.com/sdl2/sdl2-part-12-multiplayer/

目标是拥有一个能够接收来自任何人的数据包的 udp 服务器。问题是即使路由器的端口打开,它也根本无法通过互联网接收。

最佳答案

(代表 OP 发布)

这已经基本解决了。问题不在于代码,而是我的 isp 给我的调制解调器。可以并建议购买自己的调制解调器(facepalm)。

关于c++ - sdl_net udp 服务器设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42864996/

相关文章:

c++ - 使用堆栈的队列

c++ - SDL_net UDP 包数据

SDL_net 2.0 多线程

c++ - 基于 TCP/IP 的 HTTP?

java - Java 或 C++ 中的 API,用于读取机读区旅行证件(护照)代码

c++ - 是否有一种(文学)算法可将每个传入边缘的节点拆分为一个节点?

具有STL容器的c++函数模板特化

java - 如何修复它才能捕获提到的 URL 格式?