2017-03-17 119 views
0

我已經看過教程和許多其他地方如何做到這一點,但我仍然有麻煩讓這個工作。有趣的是,我確實找到了一個教程(這是我從中獲得此代碼的地方),以瞭解如何設置一個非常適合基本示例的UDP聊天程序。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中的文件,如果這是必要的只是問我會發布整個項目了在回購的人蔘考。但是我希望答案是非常簡單的,我只是不停地看一眼。

下面是我從中獲得代碼的教程鏈接。 http://headerphile.com/sdl2/sdl2-part-12-multiplayer/

目標是建立一個能夠接收來自任何人的數據包的udp服務器。問題是,即使打開路由器的端口,它也不會通過互聯網接收。

+0

步驟1:獲取網絡嗅探器。我喜歡wireshark我自己:https://www.wireshark.org/ ie:你不知道數據包來自哪裏,去哪裏,而他們在哪裏掉下去而不看它們。 (也可能檢查開放端口列表) – ebyrob

+0

我從來沒有想過使用wireshark這種方式,也沒有在Windows上使用它...天才感謝。 – user3440251

+0

在閱讀我所能瞭解的一些內容之後,無需瞭解有關SDL網絡庫的任何信息。 **數據包最終沒有收到。**無論是否在防火牆中,UDP都會被收到。我首先通過服務器上的嗅探器確信數據包確實到達100%。這會告訴你,如果客戶端沒有發送或防火牆阻塞(軟件或硬件)或服務器正在接收數據並且沒有在調試器中響應(不聽)時出現問題。 – ebyrob

回答

0

(發佈代表OP)的

這是非常解決。問題不在於我的isp給我的modem。變成可能,並建議購買你自己的調制解調器(facepalm)。

+1

謝謝你。標記爲答案。 – user3440251