C语言Windows公网转发工具(内网穿透)

C语言Windows公网转发工具(内网穿透),第1张

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;
		}
	}
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/3002550.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-27
下一篇 2022-09-27

发表评论

登录后才能评论

评论列表(0条)

保存