【问题标题】:Why can't I connect to server via actual public IP?为什么我不能通过实际的公共 IP 连接到服务器?
【发布时间】:2014-05-23 22:01:37
【问题描述】:

我是网络编程的新手,我尝试做回显客户端和服务器。它可以通过 localhost (127.0.0.1) 和 192.168.1.35 正常工作,但不能通过我的实际 IP。所以不可能通过 Internet 连接到我的服务器。但是,我在本地网络中检查了它并且它有效。
你可以试试client。如果连接完成,客户端会显示适当的消息。有两个客户。对于 IP 192.168.1.35 和我的实际 IP,我可以通过 such 和类似服务获得。有几个库应该与exe 位于同一目录中。

还有一个问题。我的服务器通过这些行显示什么?

tcp::endpoint ep = *iter++;
std::cout << ep << std::endl;

输出是:

[fe80::5100:812f:ad7c:a6dc%13]:0
192.168.1.35:0

我只是想获得我的 IP,而第二个是一个 IP,尽管它是本地的。但是第一个是什么?
谢谢!

我使用 MSVS 2013、Boost::Asio、Windows 7。
这是代码:
server.cpp

#ifdef WIN32
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#endif

#include <iostream>

#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
using namespace boost::asio;
using namespace boost::posix_time;
using boost::system::error_code;

io_service service;
size_t read_complete(char * buff, const error_code & err, size_t bytes) {
    if (err) return 0;
    bool found = std::find(buff, buff + bytes, '\n') < buff + bytes;
    // we read one-by-one until we get to enter, no buffering
    return found ? 0 : 1;
}

void handle_connections() {
    ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::tcp::v4(), 8001));
    char buff[1024];
    while (true) {
        ip::tcp::socket sock(service);
        acceptor.accept(sock);
        int bytes = read(sock, buffer(buff),
            boost::bind(read_complete, buff, _1, _2));
        std::string msg(buff, bytes);
        sock.write_some(buffer(msg));
        sock.close();
    }
}

int main(int argc, char* argv[]) {
    using boost::asio::ip::tcp;
    boost::asio::io_service io_service;
    tcp::resolver resolver(io_service);
    tcp::resolver::query query(boost::asio::ip::host_name(), "");
    tcp::resolver::iterator iter = resolver.resolve(query);
    tcp::resolver::iterator end; // End marker.
    while (iter != end)
    {
        tcp::endpoint ep = *iter++;
        std::cout << ep << std::endl;
    }
    handle_connections();
}

client.cpp

#ifdef WIN32
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#endif


#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
using namespace boost::asio;
using boost::system::error_code;
io_service service;

size_t read_complete(char * buf, const error_code & err, size_t bytes) {
    if (err) return 0;
    bool found = std::find(buf, buf + bytes, '\n') < buf + bytes;
    // we read one-by-one until we get to enter, no buffering
    return found ? 0 : 1;
}

//ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1"), 8001);
ip::tcp::endpoint ep(ip::address::from_string("192.168.1.35"), 8001);
void sync_echo(std::string msg) {
    msg += "\n";
    ip::tcp::socket sock(service);
    sock.connect(ep);
    sock.write_some(buffer(msg));
    char buf[1024];
    int bytes = read(sock, buffer(buf), boost::bind(read_complete, buf, _1, _2));
    std::string copy(buf, bytes - 1);
    msg = msg.substr(0, msg.size() - 1);
    std::cout << "server echoed our " << msg << ": "
        << (copy == msg ? "OK" : "FAIL") << std::endl;
    sock.close();
}

int main(int argc, char* argv[]) {
    // connect several clients
    char* messages[] = { "John says hi", "so does James",
        "Lucy just got home", "Boost.Asio is Fun!", 0 };
    boost::thread_group threads;
    for (char ** message = messages; *message; ++message) {
        threads.create_thread(boost::bind(sync_echo, *message));
        boost::this_thread::sleep(boost::posix_time::millisec(100));
    }
    threads.join_all();

    char ch;
    std::cin >> ch;
}

【问题讨论】:

  • 我对 92.168.1.35 感到困惑,但现在我意识到您可能是指 192.168.1.35?
  • 是的,对不起。在程序中我使用了正确的 IP。
  • This answer 包含一些与网络相关的一般问题和建议。

标签: c++ sockets tcp network-programming boost-asio


【解决方案1】:

如果您想从外部 LAN 连接到您的 PC 到端口 8001,您必须在路由器中打开此端口并告诉您的路由器如何处理端口 8001 上的传入连接。如果您的路由器公共 IP 是 92.168.1.35 并且您正在本地 PC 192.168.1.35 上的 8001 端口上监听,然后您必须在 Web 浏览器中打开路由器配置页面,转到端口转发/端口触发并建立路由器的端口 8001 到 192.168.1.35 8001 的转发。还有确保您的服务器侦听 0.0.0.0(C 代码中的 INADDR_ANY)而不是您的 LAN 接口。

在此之后,您可以检查应用程序是否正在侦听端口 8001:

sudo netstat -anlpl | grep 8001

【讨论】:

  • 感谢您的详细解答。我转发了端口,但它仍然不起作用。防火墙已关闭。如何检查服务器是否监听 0.0.0.0? acceptor.local_endpoint().address() 在与套接字的任何连接之前返回 0.0.0.0。对吗?
  • sudo netstat -anlpl | grep 8001
  • 如果我不打开 8001 端口,客户端会立即崩溃。但是当我这样做时,它会运行一段时间没有输出,然后无论如何都会崩溃。
  • 只有在通过公共 IP 或 LAN 连接时才会崩溃吗?
  • 尝试 telnet 192.168.1.35 8001,然后尝试 telnet PUBLIC_IP 8001。比较
【解决方案2】:

我只是想获得我的 IP,而第二个是一个 IP,虽然它是本地的。但是第一个是什么?

第一个是你的ipv6地址

它在“外部”不起作用的原因可能是路由或防火墙。

确保端口 138001 已路由到您的计算机且未被阻塞。

【讨论】:

  • 为什么是 13? OP 在 8001 上连接
  • 哦。正确的。白天通常在 13 点收听。更正
猜你喜欢
  • 2016-12-25
  • 1970-01-01
  • 2017-10-07
  • 2013-06-07
  • 2021-08-22
  • 2016-04-04
  • 2016-01-11
  • 2017-03-01
  • 1970-01-01
相关资源
最近更新 更多