当前位置:   article > 正文

搭建互联网可访问的TCP服务器(基于Ngrok实现)_ngrok tcp

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<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<string.h>
#include<arpa/inet.h>
#include<unistd.h>

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 多进程、多线程服务器通过这个思路,实现互联网连接,真的很赞!。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/886218
推荐阅读
相关标签
  

闽ICP备14008679号