通过Internet使用UDP和c++发送消息



我创建了一个简单的客户机/服务器程序,其中客户机能够向服务器发送消息。

这在我的本地计算机上工作,甚至在同一网络上的不同计算机上运行时,当我修改客户端程序中的IP_ADDRESS为服务器的IP地址时也可以工作。

但是,当使用不属于同一网络的设备进行测试时,即使我将其更改为我的公共IP地址,这也不起作用。我很确定它必须以某种方式使用我的公共IP地址以及我的服务器的IP地址,以便按照我的意图工作,如果我正确理解事情。然而,我不确定我将如何去实现它。

最终,我想知道的是,我如何通过Internet使用UDP和c++将单个消息从一个已知设备发送到另一个已知设备?除此之外,我真的不关心具体的实现,所以我可以将其用于我正在制作的电子游戏。

服务器:

#include <iostream>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
int main()
{
WSADATA wsadata;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &wsadata);
if (wsOk != 0)
{
std::cout << "Cannot Start Winsockn";
return -1;
}
SOCKET in = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in serverHint;
serverHint.sin_addr.S_un.S_addr = ADDR_ANY;
serverHint.sin_family = AF_INET;
serverHint.sin_port = htons(54000);
if (bind(in, (sockaddr*) &serverHint, sizeof(serverHint)) == SOCKET_ERROR)
{
std::cout << "Can't Bind Socket " << WSAGetLastError() << std::endl;
return -1;
}
sockaddr_in client;
int clientLength = sizeof(client);
ZeroMemory(&client, clientLength);
char buffer[1024];

while (true)
{
ZeroMemory(&buffer, sizeof(buffer));
int numOfBytes = recvfrom(in, buffer, sizeof(buffer), 0, (sockaddr*)  &client, &clientLength);
if (numOfBytes == SOCKET_ERROR)
{
std::cout << "Error Recieving Client Message " << WSAGetLastError() << std::endl;
continue;
}
char clientIP[256];
ZeroMemory(clientIP, sizeof(clientIP));
inet_ntop(AF_INET, &client.sin_addr, clientIP, sizeof(clientIP));
std::cout << "Message Received From [" << clientIP << "] = " << buffer << std::endl;
}
closesocket(in);
WSACleanup();
}

客户:

#include <iostream>
#include <thread>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
const char* IP_ADDRESS = "127.0.0.1";
int main()
{
WSADATA wsadata;
WORD version = MAKEWORD(2, 2);
int wsOk = WSAStartup(version, &wsadata);
if (wsOk != 0)
{
std::cout << "Cannot Start Winsockn";
return -1;
}
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(54000);
inet_pton(AF_INET, IP_ADDRESS, &server.sin_addr);
SOCKET out = socket(AF_INET, SOCK_DGRAM, 0);
std::string message = "Hello!n";
for (size_t index = 0; index < 100; index++)
{
int sendOk = sendto(out, message.c_str(), message.size() + 1, 0, (sockaddr*) &server, sizeof(server));
if (sendOk == SOCKET_ERROR)
std::cout << "Failed To Send" << WSAGetLastError() << std::endl;
}
closesocket(out);
WSACleanup();
return 0;
}

我尝试在与服务器相同的计算机上运行我的客户端,它工作,并且还尝试在同一网络中的不同设备上运行我的客户端,当我更新我的IP_ADDRESS时,它工作。然而,当我的客户端是外部网络的一部分时,它没有工作,尽管连接到互联网和IP_ADDRESS被修改为服务器的公共IP地址。

如今,随着WiFi的普遍使用和每个地点需要接入互联网的多个设备,大多数设备通过本地网络路由器接入互联网。计算机直接连接到互联网调制解调器已经越来越少了。

因此,使用路由器将阻止外部客户端能够直接通过Internet访问服务器的UDP端口。在这种情况下,LAN路由器需要有端口转发在其上配置(由管理员手动配置,或通过uPNP在代码中配置)将传入的UDP数据包从路由器的公共WAN IP转发到服务器的LAN IP。然后外部客户端可以发送数据包到路由器的WAN IP,并让它们到达服务器的UDP端口供recvfrom()读取。

最新更新