C++ Winsock2 客户端未通过远程 IP 连接到服务器
C++ Winsock2 Client not connecting to server through remote IP
我正在尝试通过使用Winsock2 API来学习网络编程的基础知识。我已经成功地通过 LAN IP 地址连接,但是我已经挣扎了一天多,试图让客户端通过其公共 IP 连接到我的服务器。
我已经在我的路由器上设置了端口转发,甚至使用Wireshark来监视客户端连接请求。我在 Wireshark 中看到请求,但它从未连接到服务器,最终出现超时错误。
我很茫然,我很感激任何能为我指出正确方向的人!
这是客户端实现:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_PORT //MY PORT
#define DEFAULT_BUFLEN 512
#define SERVER_IPV4 //"MY PUBLIC IP STRING"
int main(int argc, char **argv)
{
//wsaData to hold Winsock dll information
WSADATA wsaData;
WORD wVersionRequired = MAKEWORD(2, 2);
//Attempts to load winsock dll matching required version and fills WSADATA object
int wsaInit = WSAStartup(wVersionRequired, &wsaData);
if(wsaInit != 0)
{
printf("WSAStartup failed with error code: %dn", wsaInit);
}
//If dll fails to load correct version free winsock dll resources
if(wsaData.wHighVersion != wVersionRequired)
{
printf("No usable version of Winsock.dll foundn");
WSACleanup();
return 1;
}
else
{
printf("Winsock dll 2.2 loaded correctlyn");
}
/**********************Socket Code Here**********************/
SOCKADDR_IN SockAddrIP4;
SockAddrIP4.sin_family = AF_INET;
SockAddrIP4.sin_addr.s_addr = inet_addr(SERVER_IPV4);
SockAddrIP4.sin_port = htons(DEFAULT_PORT);
/**************Create Socket****************/
//INVALID_SOCKET used like NULL
SOCKET ConnectSocket = INVALID_SOCKET;
// TODO(baruch): Only supporting IP_V4
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ConnectSocket == INVALID_SOCKET)
{
printf("socket() error: %ldn", WSAGetLastError());
//clean up address info after getaddrinfo function when socket fails
WSACleanup();
return 1;
}
/*****************Connect to socket**************/
int connectResult = connect(ConnectSocket, (SOCKADDR*)&SockAddrIP4, sizeof(SOCKADDR_IN));
if(connectResult == SOCKET_ERROR)
{
printf("Connect failed with error: %dn", WSAGetLastError());
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
else
{
printf("Connected with server: %sn", SERVER_IPV4);
}
if(ConnectSocket == INVALID_SOCKET)
{
printf("Unable to connect with servern");
WSACleanup();
return 1;
}
/*************END of Socket CODE CLEANUP********/
// TODO(baruch): close socket
WSACleanup();
}
这是服务器:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
// TODO(baruch): Only supporting ascii consider Unicode later
#undef UNICODE
#define DEFAULT_PORT //My Port
#define DEFAULT_BUFLEN 512
int main(int argc, char **argv)
{
//wsaData to hold Winsock dll information
WSADATA wsaData;
WORD wVersionRequired = MAKEWORD(2, 2);
int wsaInit = WSAStartup(wVersionRequired, &wsaData);
if(wsaInit != 0)
{
printf("WSAStartup failed with error code: %dn", wsaInit);
}
//If dll fails to load correct version free winsock dll resources
if(wsaData.wHighVersion != wVersionRequired)
{
printf("No usable version of Winsock.dll foundn");
WSACleanup();
return 1;
}
else
{
printf("Winsock dll 2.2 loaded correctlyn");
}
/**********************Socket Code Here**********************/
/**************Create Socket****************/
SOCKADDR_IN SockAddrIP4;
SockAddrIP4.sin_family = AF_INET;
SockAddrIP4.sin_addr.s_addr = INADDR_ANY;
SockAddrIP4.sin_port = htons(DEFAULT_PORT);
//INVALID_SOCKET used like NULL
SOCKET ListenSocket = INVALID_SOCKET;
// TODO(baruch): Only supporting IP_V4
// Socket for server to listen on for client connections
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ListenSocket == INVALID_SOCKET)
{
printf("socket() error: %ldn", WSAGetLastError());
//clean up address info after getaddrinfo function when socket fails
WSACleanup();
return 1;
}
/**************Bind Socket******************/
int bindResult = bind(ListenSocket, (SOCKADDR*)&SockAddrIP4, sizeof(SOCKADDR_IN));
if(bindResult == SOCKET_ERROR)
{
printf("failed to bind with error: %dn", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
/************Listen for Connections**********/
int listenResult = listen(ListenSocket, SOMAXCONN);
if(listenResult == SOCKET_ERROR)
{
printf("Listen failed, error: %dn", WSAGetLastError() );
WSACleanup();
return 1;
}
else
{
printf("Now listening for client connections...n");
}
/************Accept and Handle CLient Connections***********/
// TODO(baruch): For testing, only allowing a single client. Eventually need to create a loop to handle all client connections.
SOCKET ClientSocket;
SOCKADDR_IN connectedAddress;
int addressLength = sizeof(connectedAddress);
ClientSocket = accept(ListenSocket, (SOCKADDR *) &connectedAddress, &addressLength);
if(ClientSocket == SOCKET_ERROR)
{
printf("Accept failed, error: %dn", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
else
{
//inet_ntoa converts ip address to binary format.
char *clientIp = inet_ntoa(connectedAddress.sin_addr);
// TODO(baruch): Make sure this string correctly prints address
printf("Client connection from: %s acceptedn", clientIp);
}
/**********Handle inbound and outbound data**********/
char inBuf[DEFAULT_BUFLEN];
int dataBufLen = DEFAULT_BUFLEN;
int inDataResult, outDataResult;
do
{
inDataResult = recv(ClientSocket, inBuf, dataBufLen, 0);
if(inDataResult > 0)
{
printf("Number of bytes received: %d", inDataResult);
//Confirm to client message received
char confirmReceipt[] = "nMessage received!n";
outDataResult =
send(ClientSocket, confirmReceipt, sizeof(confirmReceipt), 0);
if(outDataResult == SOCKET_ERROR)
{
printf("Confirmation message failed with error: %dn", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
else
{
printf("Confirmation message sentn");
}
}
else if(inDataResult == 0)
{
printf("Connection closingn");
}
else
{
printf("Data receipt failed with error: %dn", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while(inDataResult > 0);
//Shutdown sending portion of socket, can still receive data
int shutDownResult = shutdown(ClientSocket, SD_SEND);
if(shutDownResult == SOCKET_ERROR)
{
printf("Shutdown failure, error: %dn", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
/*************End Socket Code Clean up Winsock dll**********/
closesocket(ClientSocket);
WSACleanup();
}
如果可以通过本地 LAN IP 地址进行连接,但不能通过公共 IP 地址进行连接,则可能是这些问题之一。
-
是否使程序能够通过 Windows 防火墙? 完全关闭Windows防火墙(暂时(只是为了确保。
-
如果客户端和服务器位于同一 NAT 后面,则 NAT 可能不允许客户端连接通过公共 IP 地址进行连接。 这称为 NAT 发夹。并非所有 NAT 都支持此功能。验证您是否可以通过服务器网络外部的客户端连接到服务器的 IP 地址。
-
如有疑问,请使用 netcat 等简单程序来测试 PC 之间的套接字连接。 简单的测试是在端口上以侦听模式运行 nc,然后使用 nc 的另一个实例连接到它。 在互联网上搜索"Netcat for Windows"。 如果您可以通过netcat连接到端口,但不能通过客户端/服务器代码连接到端口,那么代码就有问题。 如果无法通过 netcat 连接到端口,则可能是防火墙或网络配置错误。
多亏了塞尔比,我才能经历一个淘汰的过程,并确定我的服务有问题。我联系了我的ISP,他们不得不更改服务类型并给我一个真正的公共IP。默认情况下,它们使用运营商级 NAT,这意味着住宅站点被分配一个私有 IP,该 IP 由 ISP 网络中某处的"中间设备网络地址转换器"转换为公共 IP。 谢谢!
- 为什么 WinInet 在通过 FQDN 连接时无法通过协商自动进行身份验证,但如果通过 IP 连接则成功?
- C++ Winsock2 客户端未通过远程 IP 连接到服务器
- 使用 IP 帮助程序的 Windows 中活动 UDP 连接的远程地址
- 如何将请求的客户端连接的 IP 与 QTcpSocket 类中识别的 IP 之一进行比较?
- gRPC C++尝试在无法访问的 IP 上连接通道时阻止客户端
- TCP/IP 客户端是否可以连接到无法访问的 IP
- 服务器和客户端都在PC上运行.客户端可以使用PC的IP连接到服务器
- 如何从活动的 udp 连接获取远程 IP 地址和端口
- 使用静态IP地址时,ESP32 httpclient连接拒绝了
- 如何获取其他人可以使用的IP来连接到我的c 中的套接字构建
- 如何在我当前连接的网络中获取本地 IP 地址?
- 获取传入连接的源 IP 地址
- 唯一标识UDP连接-来自同一IP的多个连接
- c++winsock客户端无法使用主机IP的文本框进行连接
- 套接字连接到不存在的ip地址上的端口
- 为什么我无法在 C++ 中键入要连接的 IP
- c++结构声明和保存IP +连接的用法
- 创建一个控制台应用程序,打开TCP/IP连接并用C++、C#或Java打印输入的字符串
- 为什么我无法通过实际的公共 IP 连接到服务器?
- 特定接口上的TCP/IP连接