内网穿透 TCP打洞 【c语言实现】
来源:互联网 发布:网店加实体店加盟知乎 编辑:程序博客网 时间:2024/05/20 05:29
http://blog.163.com/lixiangqiu_9202/blog/static/535750372015128113734761/
上篇文章中做了UDP打洞,这篇当然就会是TCP打洞了,两个处于不同内网的两台机器如何通过TCP/IP协议进行链接通讯呢?这其实跟UDP打洞差不多,基本步骤是这个样子的。
假设我们有两台处于不同内网的两台机器A和B和一台众所周知外网IP的服务器S,而机器A中运行着通讯的服务端程序B运行着通讯的客户端程序,那么
1、A连接S,S记录A的外网IP与通讯的端口
2、B连接S
3、S将A与此通讯的端口号返回给A
4、S将A与此连接的IP与端口号返回给B
5、A在程序中将服务绑定并侦听在从S返回的端口
6、B使用从S返回的IP与端口连接A
这样A与B就成功连接了,这里需要注意的一点就是两个socket在同一个端口绑定的问题,socket提供了setsockopt函数,其中参数SO_REUSEADDR可以解决这个问题
下面是c语言代码示例
S中的程序
- #include <stdio.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- typedef struct sockaddr SA;
- typedef struct sockaddr_in SA_IN;
- typedef struct
- {
- struct in_addr ip;
- int port;
- }IP; //记录ip与端口
- int main(int argc,char **argv)
- {
- SA_IN server,addr;
- int sockfd;
- IP ip;
- char s;
- socklen_t addrlen=sizeof(SA_IN);
- sockfd=socket(AF_INET,SOCK_STREAM,0);
- if(sockfd == -1)
- {
- perror("socket");
- return -1;
- }
- bzero(&server,sizeof(SA_IN));
- server.sin_port=htons(8888);
- server.sin_family=AF_INET;
- server.sin_addr.s_addr=INADDR_ANY;
- if(bind(sockfd,(SA *)&server,sizeof(SA_IN)) == -1)
- {
- perror("bind");
- return -1;
- }
- if(listen(sockfd,20) == -1)
- {
- perror("listen");
- return -1;
- }
- while(1)
- {
- int newfd[2];
- newfd[0]=accept(sockfd,(SA *)&addr,&addrlen);
- //接收两个心跳包
- recv(newfd[0],&s,sizeof(char),0);
- memcpy(&ip.ip,&addr.sin_addr,sizeof(struct in_addr));
- ip.port=addr.sin_port;
- printf("%s\t%d OK\n",inet_ntoa(ip.ip),ntohs(ip.port));
- newfd[1]=accept(sockfd,(SA *)&addr,&addrlen);
- printf("%s\t%d OK\n",
- inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
- send(newfd[0],&ip,sizeof(IP),0);
- send(newfd[1],&ip,sizeof(IP),0);
- close(newfd[0]);
- close(newfd[1]);
- }
- return 0;
- }
A中的程序
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <arpa/inet.h>
- #define SER "xxx.xxx.xxx.xxx"
- #define PORT 8888
- typedef struct
- {
- struct in_addr ip;
- int port;
- }IP; //ip与端口
- typedef struct sockaddr SA;
- typedef struct sockaddr_in SA_IN;
- //回射服务
- void echo_ser(int sockfd)
- {
- char buf[1024];
- while(1)
- {
- bzero(buf,sizeof(buf));
- //接收B发来的数据
- recv(sockfd,buf,sizeof(buf)-1,0);
- printf("%s",buf);
- //向B发送数据
- send(sockfd,buf,strlen(buf),0);
- buf[strlen(buf)-1]='\0';
- if(strcmp(buf,"exit") == 0)
- break;
- }
- }
- int main(int argc,char **argv)
- {
- int sockfd,sockfd2;
- SA_IN server,addr;
- IP ip;
- socklen_t addrlen=sizeof(SA_IN);
- char s='a';
- int flags=1;
- sockfd=socket(AF_INET,SOCK_STREAM,0);
- bzero(&server,sizeof(SA_IN));
- server.sin_family=AF_INET;
- server.sin_addr.s_addr=inet_addr(SER);
- server.sin_port=htons(PORT);
- if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&flags,sizeof(int)) ==-1)
- perror("setsockopt sockfd");
- connect(sockfd,(SA *)&server,sizeof(SA_IN));
- send(sockfd,&s,sizeof(char),0);
- recv(sockfd,&ip,sizeof(IP),0);
- close(sockfd);
- sockfd2=socket(AF_INET,SOCK_STREAM,0);
- if(sockfd2 == -1)
- perror("sockfd2");
- if(setsockopt(sockfd2,SOL_SOCKET,SO_REUSEADDR,&flags,sizeof(int))== -1)
- perror("setsockopt sockfd2");
- server.sin_addr.s_addr=INADDR_ANY;
- server.sin_port=ip.port;
- if(bind(sockfd2,(SA *)&server,sizeof(SA_IN)) == -1)
- perror("bind sockfd");
- if(listen(sockfd2,20) == -1)
- perror("listen");
- echo_ser(accept(sockfd2,(SA *)&addr,&addrlen));
- close(sockfd2);
- return 0;
- }
B中的程序
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <arpa/inet.h>
- #define SER "xxx.xxx.xxx.xxx"
- #define PORT 8888
- typedef struct
- {
- struct in_addr ip;
- int port;
- }IP; //ip与端口
- typedef struct sockaddr SA;
- typedef struct sockaddr_in SA_IN;
- void echo_cli(int sockfd)
- {
- char buf[1024];
- while(1)
- {
- bzero(buf,sizeof(buf));
- printf(">");
- fflush(stdout);
- fgets(buf,sizeof(buf)-1,stdin);
- send(sockfd,buf,strlen(buf),0);
- bzero(buf,sizeof(buf));
- recv(sockfd,buf,sizeof(buf)-1,0);
- printf("%s",buf);
- buf[strlen(buf)-1]='\0';
- if(strcmp(buf,"exit") == 0)
- break;
- }
- }
- int main(int argc,char **argv)
- {
- int sockfd,sockfd2;
- SA_IN server,addr;
- IP ip;
- socklen_t addrlen=sizeof(SA_IN);
- sockfd=socket(AF_INET,SOCK_STREAM,0);
- bzero(&server,sizeof(SA_IN));
- server.sin_family=AF_INET;
- server.sin_addr.s_addr=inet_addr(SER);
- server.sin_port=htons(PORT);
- connect(sockfd,(SA *)&server,sizeof(SA_IN));
- recv(sockfd,&ip,sizeof(IP),0);
- close(sockfd);
- sockfd2=socket(AF_INET,SOCK_STREAM,0);
- server.sin_addr=ip.ip;
- server.sin_port=ip.port;
- while(connect(sockfd2,(SA *)&server,sizeof(SA_IN)) == -1)
- perror("connect");
- echo_cli(sockfd2);
- close(sockfd2);
- return 0;
- }
阅读全文
0 0
- 内网穿透 TCP打洞 【c语言实现】
- 内网穿透&UDP打洞
- 内网穿透&UDP打洞
- 内网穿透&UDP打洞
- ngrok内网穿透,打洞
- 简单实现服务器tcp内网穿透
- 穿透内网,连接动态ip,内网ip打洞-----p2p实现原理
- P2P 穿透内网,连接动态ip,内网ip打洞,p2p实现原理
- 穿透内网,连接动态ip,内网ip打洞-----p2p实现原理
- 穿透内网,连接动态ip,内网ip打洞-----p2p实现原理
- 用TCP穿透NAT(TCP打洞)的实现
- 用TCP穿透NAT(TCP打洞)的实现
- C语言实现UDP打洞
- C语言实现UDP打洞
- C语言实现UDP打洞
- p2p技术之tcp内网穿透 java实现版
- p2p技术之tcp内网穿透 java实现版
- 【原创】IP摄像头技术纵览(七)---P2P技术—UDP打洞实现内网NAT穿透
- 谷歌和Verily发布新研究,通过AI分析视网膜图像可检测心脏病
- javax.el.PropertyNotFoundException: Property 'name' not found on type java.lang.String
- 潘再生:智能制造的综合技术体系和中控方案
- 学习笔记:Fully Convolutional Networks for Segmantic Segmentation
- ajaxStop事件不执行
- 内网穿透 TCP打洞 【c语言实现】
- 给应用添加shortcut功能
- 工作感悟
- 平安科技与天方达签署合作协议,开创智能体检新时代
- 青云 QingCloud 全新双引擎大数据服务 SparkMR 正式上线
- 离开百度的吴韧,这两年做了什么?
- (一)关于socket编程的一些基础数据类型
- 申请Apple ID出现“An unknown error has occurred.”(发生了未知错误)的解决方案一
- 机器学习数据库