不同网络之间的套接字编程
Socket programming between different networks
我正在用 c++ 开发一个客户端-服务器程序,用于将数据从一台计算机传输到另一台计算机。
一切正常,但现在我被要求让它在不同网络的计算机上工作。我到处搜索,但找不到可靠的解决方案。
我看过 TCP 打洞解决方案,但似乎无法在任何地方找到如何在 C++ 中实现它。
我希望它像 teamviewer 一样工作,但没有中间服务器。
以编程方式将我的客户端(在一台计算机上)连接到服务器(在不同网络中的另一台计算机上)。
#include "../include/ip_tunnel_ms_windows_20180815.h"
#include "../include/message_processor_common_20190410.h"
SOCKET clientSocket;
int n = 0;
void IPTunnel::initialize(void)
{
if (inputSignals.empty()) {
printf("server%d\n", n++);
if (!server()) {
printf("Error opening server\n");
::exit(1);
}
}
else {
printf("client%d\n", n++);
if (!client()) {
printf("Error opening client\n");
::exit(1);
}
}
}
bool IPTunnel::runBlock(void)
{
.....
(transmit data)
.....
return true;
}
void IPTunnel::terminate(void) {
closesocket(clientSocket);
WSACleanup();
}
bool IPTunnel::server() {
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't Initialize winsock! Quitting" << endl;
return false;
}
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create a socket! Quitting" << endl;
return false;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = ntohs(tcpPort);
//inet_pton(AF_INET, (PCSTR)remoteMachineIpAddress.c_str(), &hint.sin_addr.s_addr); // hint.sin_addr.S_un.S_addr = inet_addr(ipAddressServer.c_str());
hint.sin_addr.S_un.S_addr = INADDR_ANY;
if (::bind(listening, (sockaddr*)& hint, sizeof(hint)) < 0) {
printf("\n ERROR on binding");
return false;
}
if (listen(listening, SOMAXCONN) == -1) {
printf("\n ERROR on binding");
return false;
}
sockaddr_in client;
int clientSize = sizeof(client);
clientSocket = accept(listening, (sockaddr*)& client, &clientSize);
char host[NI_MAXHOST];
char service[NI_MAXSERV];
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXSERV);
if (getnameinfo((sockaddr*)& client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " <<
ntohs(client.sin_port) << endl;
}
return true;
}
bool IPTunnel::client() {
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0)
{
cerr << "Can't start Winsock, Err #" << wsResult << endl;
return false;
}
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET)
{
cerr << "Can't create socket, Err #" << WSAGetLastError() << endl;
WSACleanup();
return false;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(tcpPort);
inet_pton(AF_INET, remoteMachineIpAddress.c_str(), &hint.sin_addr);
int connResult = -2;
while (connResult != 0 || numberOfTrials == 0) {
connResult = connect(clientSocket, (sockaddr*)& hint, sizeof(hint));
if (connResult == SOCKET_ERROR)
{
cerr << "Can't connect to server, Err #" << WSAGetLastError() << endl;
cerr << "Waiting " << timeIntervalSeconds << " seconds." << endl;
}
Sleep(timeIntervalSeconds * 1000);
;
if (--numberOfTrials == 0) {
cerr << "Reached maximum number of attempts." << endl;
::exit(1);
}
}
cout << "Connected!\n";
return true;
}
definition of hole punching包括:
Both clients initiate a connection to an unrestricted server
你说:
I want it to work like teamviewer but without an intermediary server
一般情况下是不可能的。
我正在用 c++ 开发一个客户端-服务器程序,用于将数据从一台计算机传输到另一台计算机。
一切正常,但现在我被要求让它在不同网络的计算机上工作。我到处搜索,但找不到可靠的解决方案。
我看过 TCP 打洞解决方案,但似乎无法在任何地方找到如何在 C++ 中实现它。
我希望它像 teamviewer 一样工作,但没有中间服务器。 以编程方式将我的客户端(在一台计算机上)连接到服务器(在不同网络中的另一台计算机上)。
#include "../include/ip_tunnel_ms_windows_20180815.h"
#include "../include/message_processor_common_20190410.h"
SOCKET clientSocket;
int n = 0;
void IPTunnel::initialize(void)
{
if (inputSignals.empty()) {
printf("server%d\n", n++);
if (!server()) {
printf("Error opening server\n");
::exit(1);
}
}
else {
printf("client%d\n", n++);
if (!client()) {
printf("Error opening client\n");
::exit(1);
}
}
}
bool IPTunnel::runBlock(void)
{
.....
(transmit data)
.....
return true;
}
void IPTunnel::terminate(void) {
closesocket(clientSocket);
WSACleanup();
}
bool IPTunnel::server() {
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);
int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't Initialize winsock! Quitting" << endl;
return false;
}
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create a socket! Quitting" << endl;
return false;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = ntohs(tcpPort);
//inet_pton(AF_INET, (PCSTR)remoteMachineIpAddress.c_str(), &hint.sin_addr.s_addr); // hint.sin_addr.S_un.S_addr = inet_addr(ipAddressServer.c_str());
hint.sin_addr.S_un.S_addr = INADDR_ANY;
if (::bind(listening, (sockaddr*)& hint, sizeof(hint)) < 0) {
printf("\n ERROR on binding");
return false;
}
if (listen(listening, SOMAXCONN) == -1) {
printf("\n ERROR on binding");
return false;
}
sockaddr_in client;
int clientSize = sizeof(client);
clientSocket = accept(listening, (sockaddr*)& client, &clientSize);
char host[NI_MAXHOST];
char service[NI_MAXSERV];
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXSERV);
if (getnameinfo((sockaddr*)& client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " <<
ntohs(client.sin_port) << endl;
}
return true;
}
bool IPTunnel::client() {
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0)
{
cerr << "Can't start Winsock, Err #" << wsResult << endl;
return false;
}
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET)
{
cerr << "Can't create socket, Err #" << WSAGetLastError() << endl;
WSACleanup();
return false;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(tcpPort);
inet_pton(AF_INET, remoteMachineIpAddress.c_str(), &hint.sin_addr);
int connResult = -2;
while (connResult != 0 || numberOfTrials == 0) {
connResult = connect(clientSocket, (sockaddr*)& hint, sizeof(hint));
if (connResult == SOCKET_ERROR)
{
cerr << "Can't connect to server, Err #" << WSAGetLastError() << endl;
cerr << "Waiting " << timeIntervalSeconds << " seconds." << endl;
}
Sleep(timeIntervalSeconds * 1000);
;
if (--numberOfTrials == 0) {
cerr << "Reached maximum number of attempts." << endl;
::exit(1);
}
}
cout << "Connected!\n";
return true;
}
definition of hole punching包括:
Both clients initiate a connection to an unrestricted server
你说:
I want it to work like teamviewer but without an intermediary server
一般情况下是不可能的。