前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内网穿透 TCP打洞 【c语言实现】

内网穿透 TCP打洞 【c语言实现】

作者头像
战神伽罗
发布2019-07-24 10:33:41
4K0
发布2019-07-24 10:33:41
举报

上篇文章中做了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中的程序

  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <sys/types.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <arpa/inet.h>
  8. #include <netinet/in.h>
  9. typedef struct sockaddr SA;
  10. typedef struct sockaddr_in SA_IN;
  11. typedef struct
  12. {
  13. struct in_addr ip;
  14. int port;
  15. }IP; //记录ip与端口
  16. int main(int argc,char **argv)
  17. {
  18. SA_IN server,addr;
  19. int sockfd;
  20. IP ip;
  21. char s;
  22. socklen_t addrlen=sizeof(SA_IN);
  23. sockfd=socket(AF_INET,SOCK_STREAM,0);
  24. if(sockfd == -1)
  25. {
  26. perror("socket");
  27. return -1;
  28. }
  29. bzero(&server,sizeof(SA_IN));
  30. server.sin_port=htons(8888);
  31. server.sin_family=AF_INET;
  32. server.sin_addr.s_addr=INADDR_ANY;
  33. if(bind(sockfd,(SA *)&server,sizeof(SA_IN)) == -1)
  34. {
  35. perror("bind");
  36. return -1;
  37. }
  38. if(listen(sockfd,20) == -1)
  39. {
  40. perror("listen");
  41. return -1;
  42. }
  43. while(1)
  44. {
  45. int newfd[2];
  46. newfd[0]=accept(sockfd,(SA *)&addr,&addrlen);
  47. //接收两个心跳包
  48. recv(newfd[0],&s,sizeof(char),0);
  49. memcpy(&ip.ip,&addr.sin_addr,sizeof(struct in_addr));
  50. ip.port=addr.sin_port;
  51. printf("%s\t%d OK\n",inet_ntoa(ip.ip),ntohs(ip.port));
  52. newfd[1]=accept(sockfd,(SA *)&addr,&addrlen);
  53. printf("%s\t%d OK\n",
  54. inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
  55. send(newfd[0],&ip,sizeof(IP),0);
  56. send(newfd[1],&ip,sizeof(IP),0);
  57. close(newfd[0]);
  58. close(newfd[1]);
  59. }
  60. return 0;
  61. }

A中的程序

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/socket.h>
  5. #include <sys/types.h>
  6. #include <arpa/inet.h>
  7. #define SER "xxx.xxx.xxx.xxx"
  8. #define PORT 8888
  9. typedef struct
  10. {
  11. struct in_addr ip;
  12. int port;
  13. }IP; //ip与端口
  14. typedef struct sockaddr SA;
  15. typedef struct sockaddr_in SA_IN;
  16. //回射服务
  17. void echo_ser(int sockfd)
  18. {
  19. char buf[1024];
  20. while(1)
  21. {
  22. bzero(buf,sizeof(buf));
  23. //接收B发来的数据
  24. recv(sockfd,buf,sizeof(buf)-1,0);
  25. printf("%s",buf);
  26. //向B发送数据
  27. send(sockfd,buf,strlen(buf),0);
  28. buf[strlen(buf)-1]='\0';
  29. if(strcmp(buf,"exit") == 0)
  30. break;
  31. }
  32. }
  33. int main(int argc,char **argv)
  34. {
  35. int sockfd,sockfd2;
  36. SA_IN server,addr;
  37. IP ip;
  38. socklen_t addrlen=sizeof(SA_IN);
  39. char s='a';
  40. int flags=1;
  41. sockfd=socket(AF_INET,SOCK_STREAM,0);
  42. bzero(&server,sizeof(SA_IN));
  43. server.sin_family=AF_INET;
  44. server.sin_addr.s_addr=inet_addr(SER);
  45. server.sin_port=htons(PORT);
  46. if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&flags,sizeof(int)) == -1)
  47. perror("setsockopt sockfd");
  48. connect(sockfd,(SA *)&server,sizeof(SA_IN));
  49. send(sockfd,&s,sizeof(char),0);
  50. recv(sockfd,&ip,sizeof(IP),0);
  51. close(sockfd);
  52. sockfd2=socket(AF_INET,SOCK_STREAM,0);
  53. if(sockfd2 == -1)
  54. perror("sockfd2");
  55. if(setsockopt(sockfd2,SOL_SOCKET,SO_REUSEADDR,&flags,sizeof(int)) == -1)
  56. perror("setsockopt sockfd2");
  57. server.sin_addr.s_addr=INADDR_ANY;
  58. server.sin_port=ip.port;
  59. if(bind(sockfd2,(SA *)&server,sizeof(SA_IN)) == -1)
  60. perror("bind sockfd");
  61. if(listen(sockfd2,20) == -1)
  62. perror("listen");
  63. echo_ser(accept(sockfd2,(SA *)&addr,&addrlen));
  64. close(sockfd2);
  65. return 0;
  66. }

B中的程序

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/socket.h>
  5. #include <sys/types.h>
  6. #include <arpa/inet.h>
  7. #define SER "xxx.xxx.xxx.xxx"
  8. #define PORT 8888
  9. typedef struct
  10. {
  11. struct in_addr ip;
  12. int port;
  13. }IP; //ip与端口
  14. typedef struct sockaddr SA;
  15. typedef struct sockaddr_in SA_IN;
  16. void echo_cli(int sockfd)
  17. {
  18. char buf[1024];
  19. while(1)
  20. {
  21. bzero(buf,sizeof(buf));
  22. printf(">");
  23. fflush(stdout);
  24. fgets(buf,sizeof(buf)-1,stdin);
  25. send(sockfd,buf,strlen(buf),0);
  26. bzero(buf,sizeof(buf));
  27. recv(sockfd,buf,sizeof(buf)-1,0);
  28. printf("%s",buf);
  29. buf[strlen(buf)-1]='\0';
  30. if(strcmp(buf,"exit") == 0)
  31. break;
  32. }
  33. }
  34. int main(int argc,char **argv)
  35. {
  36. int sockfd,sockfd2;
  37. SA_IN server,addr;
  38. IP ip;
  39. socklen_t addrlen=sizeof(SA_IN);
  40. sockfd=socket(AF_INET,SOCK_STREAM,0);
  41. bzero(&server,sizeof(SA_IN));
  42. server.sin_family=AF_INET;
  43. server.sin_addr.s_addr=inet_addr(SER);
  44. server.sin_port=htons(PORT);
  45. connect(sockfd,(SA *)&server,sizeof(SA_IN));
  46. recv(sockfd,&ip,sizeof(IP),0);
  47. close(sockfd);
  48. sockfd2=socket(AF_INET,SOCK_STREAM,0);
  49. server.sin_addr=ip.ip;
  50. server.sin_port=ip.port;
  51. while(connect(sockfd2,(SA *)&server,sizeof(SA_IN)) == -1)
  52. perror("connect");
  53. echo_cli(sockfd2);
  54. close(sockfd2);
  55. return 0;
  56. }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档