基于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;
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;
}
编译服务器,并运行。
gcc sever.c
./a.out 8765
5.在其他电脑上运行TCP工具,运行TCP客户端,输入隧道供应商提供的域名和端口号,开启TCP连接,此时接收到字符串 hello,说明TCP 连接成功,发送消息,服务器会把消息回发给客户端,TCP连接成功。
linux 中 nc 是tcp/udp调试工具(俗称脑残)
6.遇到的问题:Fail to accept :Invalid argument ;当客户端连接的瞬间,服务器停止运行。
解决办法:服务器代码中accept ()函数中,把addrlen这个参数在使用前初始化一下:
int addr_len=0;
addr_len=sizeof(struct sockaddr);
int counnd=accept(sockfd,(struct sockaddr *)&caddr,&addr_len);
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
accept ()函数用法参考TCP通信相关函数。
7.总结:通过Ngrok隧道,把本地端口映射到互联网,从而实现,互联网访问本地服务器。在学习网络编程时,可以把只能在局域网内调试的TCP、UDP 多进程、多线程服务器通过这个思路,实现互联网连接,真的很赞!。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)