• 基于Ngrok 内网穿透的TCP服务器


    基于Ngrok 内网穿透的TCP服务器

    实现目的:在本地搭建TCP服务器,通过Ngrok 内网穿透,把本地TCP服务器的端口映射到互联网上,达到通过TCP 在互联网上访问本地服务器的目的。

    物理环境:树莓派4B 4G

    系统:Ubuntu 22.04

    一、项目准备

    1.获得Ngrok 内网穿透隧道的域名和端口号;

    2.把树莓派上安装隧道客户端,并运行客户端,使隧道打开;(这个时候,可以通过隧道供应商提供的域名和端口号通过ssh 访问树莓派服务器,ssh使用的端口号为:22);

    3.在隧道供应商处修改本地端口为 127.0.0.1:8765(冒号后面的端口号要大于5000,随自己喜欢都可以);

    4.在树莓派上编译一下代码

    文件名:sever.c

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    
    int main(int argc, const char *argv[])
    {
    	if(argc<2)
    	{
    		fprintf(stderr,"usage:%s 8888",argv[0]);
    		return 0;
    	}
    	int sockfd=socket(AF_INET,SOCK_STREAM,0);
    	if(sockfd<0)
    	{
    		perror("Fail to socket");
    		return 0;
    	}
    	struct sockaddr_in saddr,caddr;
    
    	//socklen_t caddr_len;
    	memset(&saddr,0,sizeof(saddr));
    	memset(&caddr,0,sizeof(caddr));
    	saddr.sin_family=AF_INET;
    	saddr.sin_port=htons(atoi(argv[1]));
    	saddr.sin_addr.s_addr=htons(INADDR_ANY);
    
    	int ret=bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
    	if(ret<0)
    	{
    		perror("Fail to bind");
    		return 0;
    	}
    
    	ret =listen(sockfd,5);
    	if(ret<0)
    	{
    		perror("Fail to listen");
    		return 0;
    	}
    
    	int caddr_len=0;
    	caddr_len=sizeof(struct sockaddr);
    	
    	while(1)
    	{
    		int connfd=accept(sockfd,(struct sockaddr *)&caddr,&caddr_len);
    		if(connfd<0)
    		{
    			perror("Fail to accept");
    			return 0;
    		}
    		char buf[1024]={0};
    		while(1)
    		{
    			memset(buf,0,sizeof(buf));
    			ret=read(connfd,buf,sizeof(buf));
    			if(ret==0)
    			{
    				printf("客户端异常退出!\n");
    				break;
    			}
    			else if(ret==-1)
    			{
    				perror("Fail to read");
    				break;
    			}
    			if(strncmp("quit",buf,4)==0)
    			{
    				printf("客户端主动退出!\n");
    				break;
    			}
    			printf("read: %d bytes:%s",ret,buf);
    
    			write(connfd,buf,ret);
    		}
    		close(connfd);
    		write(connfd,buf,ret);
    
    
    	}
    
    	close(sockfd);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    编译服务器,并运行。

    gcc sever.c//编译
    ./a.out 8765 //运行服务器,8765为端口号
    
    • 1
    • 2

    5.在其他电脑上运行TCP工具,运行TCP客户端,输入隧道供应商提供的域名和端口号,开启TCP连接,此时接收到字符串 hello,说明TCP 连接成功,发送消息,服务器会把消息回发给客户端,TCP连接成功。

    linux 中 nc 是tcp/udp调试工具(俗称脑残)
    在这里插入图片描述

    6.遇到的问题:Fail to accept :Invalid argument ;当客户端连接的瞬间,服务器停止运行。

    在这里插入图片描述

    解决办法:服务器代码中accept ()函数中,把addrlen这个参数在使用前初始化一下:

    //把accept函数修改如下
    int addr_len=0;
    addr_len=sizeof(struct sockaddr);
    int counnd=accept(sockfd,(struct sockaddr *)&caddr,&addr_len);
    
    • 1
    • 2
    • 3
    • 4
    int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
    //返回值:成功返回通信套接字,失败返回-1;
    //addr :客户端的地址结构的首地址;
    //addrlen:客户端地址结构体的大小的首地址;
    //注:若不想接受客户端的地址信息,addr与addrlen两个参数填NULL;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    accept ()函数用法参考TCP通信相关函数

    7.总结:通过Ngrok隧道,把本地端口映射到互联网,从而实现,互联网访问本地服务器。在学习网络编程时,可以把只能在局域网内调试的TCP、UDP 多进程、多线程服务器通过这个思路,实现互联网连接,真的很赞!。

  • 相关阅读:
    7.22 SpringBoot项目实战【收藏 和 取消收藏】
    jmeter录制https脚本
    羊大师:羊奶的多元价值,从餐桌到保健,一奶多用
    时序分解 | Matlab实现CEEMD互补集合经验模态分解时间序列信号分解
    浏览器基本原理
    关于2023年编程语言使用排行我的看法
    【数据挖掘】4. 打散(Shattering) VC维数 基于VC维数和Margin的泛化定理
    Attention Is All You Need--论文笔记
    Codeforces Round 906 (Div. 2--ABC)
    携职教育:人社局通知:取得初级会计证可以申领补贴!至高1500元!
  • 原文地址:https://blog.csdn.net/jun8086/article/details/127661360