C语言写的内网穿透工具,将家用电脑的服务映射到公网。
公网服务器实现原理:
1.创建两个socket(两个不同的端口)分别监听私网服务器的连接;
2.等待私网服务器连接;
3.等待客户端连接,收到客户端的连接请求立即发送消息通知私网服务器
4.等待私网服务器发起连接
5.创建独立线程将客户端的数据与私网服务器的数据相互转发。
运行于公网程序源码
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
using namespace std;
//数据转发函数
void s1_s2(SOCKET sock1,SOCKET sock2);
int main()
{
//初始化网络库
WSADATA vs;
WSAStartup(MAKEWORD(2, 2), &vs);
//创建监听私网服务器socket与网络信息
SOCKET listen_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN listen_server_net;
listen_server_net.sin_family = AF_INET;
listen_server_net.sin_addr.S_un.S_addr = INADDR_ANY;
listen_server_net.sin_port = htons(4001);
//绑定socket与网络参数
if (::bind(listen_server, (SOCKADDR*)&listen_server_net, sizeof(listen_server_net)) == SOCKET_ERROR)
{
printf("bind 4001 error\n"); Sleep(2000); exit(-1);
}
//监听链接
if (listen(listen_server, 5) == SOCKET_ERROR)
{
printf("listen 4001 error\n"); Sleep(2000); exit(-1);
}
//创建监听客户端socket与网络信息
SOCKET listen_user = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN listen_user_net;
listen_user_net.sin_family = AF_INET;
listen_user_net.sin_addr.S_un.S_addr = INADDR_ANY;
listen_user_net.sin_port = htons(4002);
//绑定socket与网络参数
if (::bind(listen_user, (SOCKADDR*)&listen_user_net, sizeof(listen_user_net)) == SOCKET_ERROR)
{
printf("bind 4002 error\n"); Sleep(2000); exit(-1);
}
//监听链接
if (listen(listen_user, 5) == SOCKET_ERROR)
{
printf("listen 4002 error\n"); Sleep(2000); exit(-1);
}
//等待服务器连接
SOCKET to_server;
SOCKADDR_IN tmp;
int j = sizeof(tmp);
do
{
to_server = accept(listen_server, (SOCKADDR*)&tmp, &j);
} while (to_server <= 0);
printf("私网服务器:%s 连接成功 sock_ID:%d\n", inet_ntoa(tmp.sin_addr),to_server);
//循环等待用户链接
while (true)
{
SOCKET user = accept(listen_user, (SOCKADDR*)&tmp, &j);
if (user<0) continue;
printf("用户:%s 连接成功 sock_ID:%d\n",inet_ntoa(tmp.sin_addr),user);
//通知服务器有新的链接
send(to_server, "new_connet", 20, 0);
//等待服务器发起新链接
SOCKET server = accept(listen_server, (SOCKADDR*)&tmp, &j);
if (server < 0) continue;
printf("服务器:%s 发起了新的连接 sock_ID:%d\n", inet_ntoa(tmp.sin_addr), user);
//两个socket加入到相互转发线程
thread t1(s1_s2,user,server);
t1.detach();
thread t2(s1_s2, server, user);
t2.detach();
}
closesocket(listen_server);
closesocket(listen_user);
WSACleanup();
return 0;
}
//数据转发函数
void s1_s2(SOCKET sock1,SOCKET sock2)
{
while (1)
{
char data[1024] = { 0 };
int ret = recv(sock1, data, 1024, 0);
if (ret > 0)
{
send(sock2, data, ret, 0);
}
if (ret == 0)
{
closesocket(sock1);
closesocket(sock2);
return;
}
if (ret < 0)
{
closesocket(sock1);
return;
}
}
}
私网服务器实现原理
1.创建socket连接公网服务器,等待新客户连接申请
2.收到新客户连接申请,向公网服务器发起新的连接
3.创建socket向本地服务端口发起连接
4.创建独立线程将服务端口数据与客户端数据相互转发
运行在内网服务器代码
#include
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
using namespace std;
//数据转发函数
void s1_s2(SOCKET sock1, SOCKET sock2);
int main()
{
//初始化网络参数
WSADATA vs;
WSAStartup(MAKEWORD(2, 2), &vs);
//创建链接公网服务的socket与网络信息
SOCKET listen_IP = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN IP_net;
IP_net.sin_family = AF_INET;
IP_net.sin_addr.S_un.S_addr = inet_addr("103.222.189.25");
IP_net.sin_port = htons(4001);
//链接公网服务器
if (connect(listen_IP, (SOCKADDR*)&IP_net, sizeof(IP_net)) == SOCKET_ERROR)
{
printf("connect IP error\n"); Sleep(2000); exit(-1);
}
printf("connect IP success\n");
//创建服务器信息
SOCKADDR_IN server_net;
server_net.sin_family = AF_INET;
server_net.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
server_net.sin_port = htons(80);
//等待公网服务器发送消息
while (true)
{
while (true)
{
char data[128] = { 0 };
int ret = recv(listen_IP, data, 128, 0);
if (ret == 20 && !strcmp(data, "new_connet"))
{
//有新的用户链接,向公网服务器发起一个新的链接
SOCKET to_user = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (connect(to_user, (SOCKADDR*)&IP_net, sizeof(IP_net)) == SOCKET_ERROR)
{
closesocket(to_user);
continue;
}
printf("to_IP success\n");
//向服务器发起链接
SOCKET to_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (connect(to_server, (SOCKADDR*)&server_net, sizeof(server_net)) == SOCKET_ERROR)
{
perror("connect server error ");
closesocket(to_user);
continue;
}
printf("to_servre success\n");
//数据转发线程
thread t1(s1_s2, to_user, to_server);
t1.detach();
thread t2(s1_s2, to_server, to_user);
t2.detach();
}
if (ret<=0)
{
closesocket(listen_IP);
printf("IP closed\n");
exit(0);
}
}
}
}
//数据转发函数
void s1_s2(SOCKET sock1, SOCKET sock2)
{
while (1)
{
char data[1024] = { 0 };
int ret = recv(sock1, data, 1024, 0);
if (ret > 0)
{
send(sock2, data, ret, 0);
}
if (ret == 0)
{
closesocket(sock1);
closesocket(sock2);
return;
}
if (ret < 0)
{
closesocket(sock1);
return;
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)