服务器和客户端都在PC上运行.客户端可以使用PC的IP连接到服务器
A server and a client both run on a PC. Can the client connect to the server using the IP of the PC?
我是网络编程的新手,所以这让我困惑了几天。
我写了2个应用程序:一个是服务器,一个是客户端。
我希望他们做的是:当我为客户端提供IP地址时,客户端将使用提供的IP连接到机器上的服务器。
我通过在我的PC上打开服务器和客户端来测试它,并在循环返回地址(127.0.0.1(中输入。客户端连接到服务器罚款(我什至可以彼此发送短信(。
所以我尝试了进一步。我搜索了我的IP(113.20.98.124(,然后将其喂给我的客户。我希望客户也将连接到服务器,但这没有发生。客户终止并说连接定时(WSAETIMEDOUT 10060(。
我想问的是:为什么我不能使用IP告诉客户端连接到我的服务器?那是什么吗?
这是我的服务器和客户端的代码(如果我做错了什么(:
(我在Windows上使用VS2017编码(
客户端:
#include <iostream>
#include <WS2tcpip.h>
#include <winsock2.h>
#include <string>
//The port which will be used to connect to server
#define PORT "7777"
std::string getIPAddress()
{
std::string out;
std::cout << "IP/Domain to connect to: ";
std::cin >> out;
std::cin.ignore();
return out;
}
//Print out error code and exit the program in case something goes wrong
void failure_exit(std::string message, int exitVal)
{
std::cerr << message
<< " Error code: " << WSAGetLastError() << " n";
WSACleanup();
std::cin.get();
exit(exitVal);
}
int main(int argc, char *argv[])
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 0), &wsaData) != 0)
failure_exit("WSAStartup failed!", 1);
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; //AF_INET or AF_INET6 are totally fine
hints.ai_socktype = SOCK_STREAM; //TCP connection
//Get the IP from user
std::string IPconnect = getIPAddress();
//A pointer to a linked list of juicy results we can use
addrinfo *result(nullptr);
//Prepare the addrinfo for a connecting socket
if (getaddrinfo(IPconnect.c_str(), PORT, &hints, &result) != 0)
failure_exit("getaddrinfo failed!", 2);
/*PREPARING A SOCKET*/
SOCKET sockfd;
//A pointer to one of the addrinfos from result, which is a usable one
//'chosen' will also be used in connect() call
addrinfo *chosen(result);
//Run through the results got from getaddrinfo and pick the first usable addrinfo
for (; chosen != nullptr; chosen = chosen->ai_next)
{
//see if sockfd is legit to use
if ((sockfd = socket(chosen->ai_family, chosen->ai_socktype, chosen->ai_protocol)) != -1)
break;
}
freeaddrinfo(result);
//Socket preparation failed
if (sockfd<=0)
failure_exit("Socket preparation failed!", 3);
/*CONNECT!*/
std::cout << "Connecting... 20 seconds until timed out.n";
if (connect(sockfd, chosen->ai_addr, chosen->ai_addrlen) != 0)
failure_exit("Failed to connect!", 4);
std::cout << "Connected!n";
WSACleanup();
std::cin.get();
return 0;
}
服务器:
#include <iostream>
#include <WS2tcpip.h>
#include <winsock2.h>
#include <string>
//The port which this server will be using
//to listen to incoming connections
#define PORT "7777"
//Limits how many pending connections
//can be queued up
#define BACKLOG 10
void failure_exit(std::string message, int exitVal)
{
std::cerr << message
<< " Error code: " << WSAGetLastError() << " n";
WSACleanup();
std::cin.get();
exit(exitVal);
}
int main(int argc, char* argv[])
{
WSADATA wsa;
if (WSAStartup(MAKEWORD(1, 0), &wsa) != 0)
failure_exit("WSAStartup failed!", 1);
addrinfo hints;
memset(&hints, 0, sizeof(hints));
//IPv4 or IPv6 are both Ok
hints.ai_family = AF_INET;
//This addrinfo will be used for binding
hints.ai_flags = AI_PASSIVE;
//TCP connection
hints.ai_socktype = SOCK_STREAM;
addrinfo *result;
if (getaddrinfo(NULL, PORT, &hints, &result) != 0)
failure_exit("getaddrinfo failed!", 3);
//PREPARE A SOCKET
SOCKET sockfd(0);
//The usable addrinfo will be pointed to by 'chosen'
addrinfo *chosen(result);
//Loop through the results to find a suitable one
for (; chosen != nullptr; chosen = chosen->ai_next)
{
sockfd = socket(chosen->ai_family, chosen->ai_socktype, chosen->ai_protocol);
//Stop at the first usable
if (sockfd != -1)
break;
}
freeaddrinfo(result);
//Check for preparation failure
if (sockfd <= 0)
failure_exit("Socket preparation failed!", 4);
//Bind the socket above to my chosen PORT
if (bind(sockfd, chosen->ai_addr, chosen->ai_addrlen) == -1)
failure_exit("Binding failed!", 5);
//Start listening for incoming connections
if (listen(sockfd, BACKLOG) == -1)
failure_exit("Listening failed!", 6);
//The new socket to be returned by accept()
SOCKET newfd;
sockaddr_storage newConnection;
socklen_t newlength(sizeof(newConnection));
std::cout << "Anyone?n";
//Accept a pending connection
if ((newfd = accept(sockfd, reinterpret_cast<sockaddr*>(&newConnection), &newlength)) == -1)
failure_exit("Accepting connection failed!", 7);
std::cout << "Connection accepted!n";
WSACleanup();
std::cin.get();
return 0;
}
我了解的有关网络编程的任何内容均来自http://beej.us/guide/。
搜索搜索IP时,您会得到公共IP,就像外部世界所看到的那样。如果您的PC直接连接到您的Internet调制解调器,则IP属于您的PC。但是,如果您的PC位于网络路由器后面(如今与拥有许多与Internet连接的设备的家庭非常普遍(,那么IP属于您的网络路由器,而不是您的PC。
您的服务器应用只能在直接分配给正在运行的PC的本地/LAN IP上收听。如果该PC在网络路由器后面运行,则无法收听路由器的公共IP。
您的服务器代码以这种方式绑定了其侦听套接字,以使其在所有可用的IPv4 IP上听,这些IPv4 IP分配给了它正在运行的PC。要发现实际上是什么,您可以使用Windows的命令行ipconfig
工具。或者,在服务器代码中,您可以使用GetAdaptersInfo()
或GetAdaptersAddresses()
API。
如果您的客户端与服务器应用程序在同一PC/网络上运行,则可以直接连接到服务器正在侦听的任何本地/LAN IP。但是,如果客户端在另一个网络上运行(即在Internet上的另一台PC上(,则需要连接到您的公共IP。在该公共IP属于网络路由器的情况下,需要配置路由器以将给定的<PublicIP>:<PublicPort>
上的入站连接转发到服务器PC的<LanIP:LanPort>
(即,从113.20.98.124:777
转发到192.168.0.1:777
,或实际分配了任何IP到服务器PC(。
- "unknown ca"自生成的 CA、证书和客户端/服务器
- 如何将函数集合传递给客户端类,以便将它们当作客户端类本身的成员使用
- 使用调试/崩溃报告将应用程序部署到客户端
- 如何在本地机器上运行c++和javascript客户端代码(hackerbank风格)
- 如何通过套接字将文本文件的内容从服务器发送到客户端
- 从服务器传输到客户端的消息不会出现
- OpenSSL TLS服务器-使用客户端证书白名单
- 当服务中的事件被触发时,如何将响应从服务发送回客户端?
- 我可以与 python 服务器而不是 c++ 客户端建立 tcp/ip 套接字吗?
- 提升 Asio TCP 服务器 处理多个客户端
- boost::asio UDP 广播客户端仅接收"fast"数据包
- 如何绑定 C++ gRPC 客户端的网络接口
- C++套接字客户端到 Python 服务器未创建连接
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 将相机数据从服务器实时流式传输到客户端
- 如何将 Firebase 与基于 Linux 的客户端应用配合使用,以便与服务器进行双向消息通信
- GRPC C++ TLS 客户端 grpc::SslCredentials() 方法不返回
- 服务器和客户端都在PC上运行.客户端可以使用PC的IP连接到服务器
- ASIO 客户端服务器在同一台 PC 上连接正常,但在本地网络上出现故障
- 如何在客户端PC中使用编译后的DLL而不安装Windows SDK ?