TCP 仅不适用于公共 IP

发布于 2024-12-28 20:02:53 字数 1807 浏览 1 评论 0原文

我已经编写了两个函数,它们应该启动 TCP 服务器/客户端。如果我用 IP“127.0.0.1”(仅用于测试)调用它们,那么一切都会正常。但是,如果我使用计算机的公共 IP 呼叫他们,则会出现连接超时。有人知道可能是什么问题吗?

这里的代码:

服务器:

bool fSTARTED = false;
struct timeval tv;

TCP_StartServer (const int iPort, SOCKET *iSOCKET)
{
WSADATA wsa;
SOCKET iSOCKETListen;
SOCKADDR_IN tAdr;

if(!fSTARTED)
{
    if(WSAStartup(MAKEWORD(2,2), &wsa))
    {
        *iSOCKET = -1;
        return;
    }
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    fSTARTED = true;
}

iSOCKETListen = socket(AF_INET, SOCK_STREAM, 0);

memset(&tAdr, 0, sizeof(SOCKADDR_IN));
tAdr.sin_family = AF_INET;
tAdr.sin_port = htons(iPort);
tAdr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(iSOCKETListen, (SOCKADDR*) & tAdr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

if(listen(iSOCKETListen, SOMAXCONN) == SOCKET_ERROR)
{
    *iSOCKET =  0 - WSAGetLastError();
    return;
}

*iSOCKET = accept(iSOCKETListen, NULL, NULL);
if(*iSOCKET == INVALID_SOCKET)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

return;
}

客户端:

TCP_StartClient (char *sIP, const int iPort, SOCKET *iSOCKET)
{
WSADATA wsa;
SOCKADDR_IN tAdr;

if(!fSTARTED)
{
    if(WSAStartup(MAKEWORD(2,2), &wsa))
    {
        *iSOCKET = -2;
        return;
    }
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    fSTARTED = true;

}

*iSOCKET = socket(AF_INET, SOCK_STREAM, 0);
if(*iSOCKET == INVALID_SOCKET)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

memset(&tAdr, 0, sizeof(SOCKADDR_IN));
tAdr.sin_family = AF_INET;
tAdr.sin_port = htons(iPort);
tAdr.sin_addr.s_addr = inet_addr(sIP);

if(connect(*iSOCKET, (SOCKADDR*) &tAdr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
    *iSOCKET =  0 - WSAGetLastError();
    return;
}

return;
}

I've written two functions, which should start a TCP-Server/Client. If I call them with the IP "127.0.0.1" (just for testing), then everything works fine. But if I call them with the public IP of my computer, I get a connection timeout. Has anybody an idea what could be the problem?

Here the Code:

Server:

bool fSTARTED = false;
struct timeval tv;

TCP_StartServer (const int iPort, SOCKET *iSOCKET)
{
WSADATA wsa;
SOCKET iSOCKETListen;
SOCKADDR_IN tAdr;

if(!fSTARTED)
{
    if(WSAStartup(MAKEWORD(2,2), &wsa))
    {
        *iSOCKET = -1;
        return;
    }
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    fSTARTED = true;
}

iSOCKETListen = socket(AF_INET, SOCK_STREAM, 0);

memset(&tAdr, 0, sizeof(SOCKADDR_IN));
tAdr.sin_family = AF_INET;
tAdr.sin_port = htons(iPort);
tAdr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(iSOCKETListen, (SOCKADDR*) & tAdr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

if(listen(iSOCKETListen, SOMAXCONN) == SOCKET_ERROR)
{
    *iSOCKET =  0 - WSAGetLastError();
    return;
}

*iSOCKET = accept(iSOCKETListen, NULL, NULL);
if(*iSOCKET == INVALID_SOCKET)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

return;
}

Client:

TCP_StartClient (char *sIP, const int iPort, SOCKET *iSOCKET)
{
WSADATA wsa;
SOCKADDR_IN tAdr;

if(!fSTARTED)
{
    if(WSAStartup(MAKEWORD(2,2), &wsa))
    {
        *iSOCKET = -2;
        return;
    }
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    fSTARTED = true;

}

*iSOCKET = socket(AF_INET, SOCK_STREAM, 0);
if(*iSOCKET == INVALID_SOCKET)
{
    *iSOCKET = 0 - WSAGetLastError();
    return;
}

memset(&tAdr, 0, sizeof(SOCKADDR_IN));
tAdr.sin_family = AF_INET;
tAdr.sin_port = htons(iPort);
tAdr.sin_addr.s_addr = inet_addr(sIP);

if(connect(*iSOCKET, (SOCKADDR*) &tAdr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
    *iSOCKET =  0 - WSAGetLastError();
    return;
}

return;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

帅气称霸 2025-01-04 20:02:53

以下是典型的家庭计算机网络的外观(简化图和解释):

        \     Internet     /
         \/\/\/\/\/\/\/\/\/
                  |
                  | 212.60.44.90 (public IP address)
           +-------------+
           | DSL router  |
           +-------------+
                  | 10.0.0.1 (private network router)
                  |
                  | 10.0.0.2 (private network address)
           +-------------+
           |Your computer|
           +-------------+

在这种情况下,路由器正在执行 NAT 从本地 10.0.0.x 地址到公共 212.60.44.90 地址。您的计算机不知道它最终使用的公共 IP 地址,因为该信息仅存在于 DSL 路由器中。 NAT 的要点是,您的本地 10.0.0.x 网络上可能还存在其他计算机,并且它们共享相同的公共 IP 地址(因为只有一个)。

您的路由器可能还充当防火墙,防止来自互联网的随机传入连接到达您的本地计算机。通常,路由器会阻止所有此类传入连接。

鉴于上述内容,您应该能够明白为什么无法从您自己的网络内连接到公共 212.60.44.90 地址。您的计算机将请求发送到路由器,路由器从防火墙的角度忽略或阻止您的请求。

根据您的路由器,您也许能够将其配置为将传入的请求转发到您的公共 IP 地址到 10.0.0.x 网络上的特定计算机。您必须手动进行设置,并且有关如何执行此操作的说明超出了本答案的范围。

此外,您可能会注意到,您应该能够通过本地网络地址(图中的 10.0.0.2)连接到本地计算机。然而,这并不比连接到 127.0.0.1 有趣多少。

Here's how a typical home computer network looks (simplified diagram and explanation):

        \     Internet     /
         \/\/\/\/\/\/\/\/\/
                  |
                  | 212.60.44.90 (public IP address)
           +-------------+
           | DSL router  |
           +-------------+
                  | 10.0.0.1 (private network router)
                  |
                  | 10.0.0.2 (private network address)
           +-------------+
           |Your computer|
           +-------------+

In this case the router is doing NAT from your local 10.0.0.x addresses to your public 212.60.44.90 address. Your computer is unaware of the public IP address that it ends up using, because that information is only in the DSL router. The point of NAT is that there may also be other computers on your local 10.0.0.x network, and they share the same public IP address (because there is only one).

Your router probably also acts as a firewall, preventing random incoming connections from the Internet from reaching your local computers. Normally the router will block all such incoming connections.

Given the above, you should be able to see why you cannot connect to your public 212.60.44.90 address from within your own network. Your computer sends the request to the router, which either ignores or blocks your request from a firewall perspective.

Depending on your router, you may be able to configure it to forward incoming requests to your public IP address to a specific computer on your 10.0.0.x network. You would have to set up this manually, and instructions about how to do that are beyond the scope of this answer.

Also, you may notice that you should be able to connect to your local computer on your local network address (10.0.0.2 in the diagram). However, that's not much more interesting than connecting to 127.0.0.1.

转瞬即逝 2025-01-04 20:02:53

这甚至可能不是您的代码的问题。有些计算机(例如我的计算机)在尝试从外部 IP 访问时看不到自己。尝试为您的外部 IP 设置环回适配器,同时检查您的 NAT 规则。

This might not even be a problem with your code. Some computers (like mine) can't see itself when trying to access from the external IP. Try setting a loopback adapter for your external IP, also, check your NAT rules.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文