江湖上一直都有这位哥哥的传说,也有很多人说自己就他的真身!

但是。。。

今天分享一下TCP连接的P2P demo,江湖的规矩也要与时俱进。。。

————————————————————————————————————

原理之步骤(原理说了也不是那个理,做NAT的不说,谁知道呢?还不如过程呢)

一.A,B连接打洞服务器S

二.S记录下A的公网IP和端口,记录下B的公网

IP和端口

三.S将A的公网IP和端口以及B的公网端口发给B

四.S将B的公网IP和端口发给A

五. S命令B向A的公网IP和端口发起connect(打洞)

六. S命令B在B的公网端口上监听A的连接(connect)

七.S命令A向B的公网IP和端口发出连接命令(connect

// server.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <signal.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <fcntl.h>

#include <errno.h>

typedef struct IP_PORT

{

char ip[64];

int port;

}IP_PORT;

void sigint(int signum)

{

if (SIGINT==signum)

{

exit(1);

}

}

int main()

{

int listenfd;

int value = 1;

socklen_t clilen;

struct sockaddr_in cliaddr, seraddr;

int sock_a, sock_b;

char tmpaddr[128], tmpaddr_port[128], tmpaddr_port_port[128];

signal(SIGINT, sigint);

listenfd = socket(AF_INET, SOCK_STREAM, 0);

if (-1==listenfd)

{

printf("socket -server error: %s\n", strerror(errno));

return 1;

}

// reuse socket's address

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &value, sizeof(value));

// set bind server

memset(&seraddr, 0, sizeof(seraddr));

seraddr.sin_family = AF_INET;

seraddr.sin_addr.s_addr = htonl(INADDR_ANY);

seraddr.sin_port = htons(8099);

if (-1==bind(listenfd, (struct sockaddr*)&seraddr, sizeof(seraddr)))

{

printf("bind -server error: %s\n", strerror(errno));

close(listenfd);

return 1;

}

if (-1==listen(listenfd, 5))

{

printf("listen -server error: %s\n", strerror(errno));

close(listenfd);

return 1;

}

sock_a = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen);

if (-1==sock_a)

{

printf("accept -server error: %s\n", strerror(errno));

close(listenfd);

return 1;

}

inet_ntop(AF_INET, (void*)&cliaddr.sin_addr, tmpaddr, sizeof(tmpaddr));

sprintf(tmpaddr_port, "%s %d", tmpaddr, ntohs(cliaddr.sin_port));

sock_b = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen);

if (-1==sock_b)

{

printf("accept -server error: %s\n", strerror(errno));

close(sock_a);

close(listenfd);

return 1;

}

sprintf(tmpaddr_port_port, "%s %d", tmpaddr_port, ntohs(cliaddr.sin_port));

write(sock_b, tmpaddr_port_port, strlen(tmpaddr_port_port)+1);

close(sock_b);

printf("cli_a IP PORT cli_b PORT: %s\n", tmpaddr_port_port);

inet_ntop(AF_INET, (void*)&cliaddr.sin_addr, tmpaddr, sizeof(tmpaddr));

sprintf(tmpaddr_port, "%s %d", tmpaddr, ntohs(cliaddr.sin_port));

write(sock_a, tmpaddr_port, strlen(tmpaddr_port)+1);

close(sock_a);

printf("cli_b IP PORT: %s\n", tmpaddr_port);

close(listenfd);

printf("exit -server\n");

return 0;

}

//cli_a.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <signal.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <fcntl.h>

#include <errno.h>

typedef struct IP_PORT

{

char ip[64];

int port;

}IP_PORT;

void sigint(int signum)

{

if (SIGINT==signum)

{

exit(1);

}

}

int main(int argc, char **argv)

{

struct sockaddr_in seraddr;

int sockfd;

char tmpaddr_port[128];

IP_PORT peer;

int len;

char tmpbuf[128];

signal(SIGINT, sigint);

if (2!=argc)

{

printf("CmdLine should be: cli_a <IP>\n");

return 1;

}

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (-1==sockfd)

{

printf("socket -cli_a error: %s\n", strerror(errno));

return 1;

}

memset(&seraddr, 0, sizeof(seraddr));

seraddr.sin_family = AF_INET;

inet_pton(AF_INET, argv[1], &seraddr.sin_addr);

seraddr.sin_port = htons(8099);

if (0>connect(sockfd, (struct sockaddr*)&seraddr, sizeof(seraddr)))

{

printf("connect main -cli_a error: %s\n", strerror(errno));

return 1;

}

if (0>read(sockfd, tmpaddr_port, 128))

{

printf("read main -cli_a error: %s\n", strerror(errno));

return 1;

}

sscanf(tmpaddr_port, "%s %d", peer.ip, &peer.port);

// close main socket

close(sockfd);

// create new p2p client socket

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (-1==sockfd)

{

printf("socket -cli_a error: %s\n", strerror(errno));

return 1;

}

inet_pton(AF_INET, peer.ip, &seraddr.sin_addr);

seraddr.sin_port = htons(peer.port);

printf("Peer cli_b IP PORT: %s %d\n", peer.ip, peer.port);

// wait for cli_b to punch hole to cli_a self and cli_b is in accepting

sleep(5);

if (0>connect(sockfd, (struct sockaddr*)&seraddr, sizeof(seraddr)))

{

printf("connect p2p -cli_a error: %s\n", strerror(errno));

close(sockfd);

return 1;

}

len = write(sockfd, "I am a\n", strlen("I am a\n")+1);

if (0>=len)

{

printf("write p2p -cli_a error: %s\n", strerror(errno));

close(sockfd);

return 1;

}

len = read(sockfd, tmpbuf, 128);

if (0<len)

{

printf("%s", tmpbuf);

printf("\n");

}

close(sockfd);

printf("exit -cli_a\n");

return 0;

}

//cli_b.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <signal.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <fcntl.h>

#include <errno.h>

typedef struct IP_PORT

{

char ip[64];

int port;

}IP_PORT;

void sigint(int signum)

{

if (SIGINT==signum)

{

exit(1);

}

}

int main(int argc, char **argv)

{

struct sockaddr_in seraddr, cliaddr;

socklen_t clilen;

int sockfd, listenfd;

unsigned int value = 1;

char tmpaddr_port_port[128];

IP_PORT peer;

int len;

char tmpbuf[128];

int port;

signal(SIGINT, sigint);

if (2!=argc)

{

printf("CmdLine should be: cli_b <IP>\n");

return 1;

}

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (-1==sockfd)

{

printf("socket -cli_b error: %s\n", strerror(errno));

return 1;

}

memset(&seraddr, 0, sizeof(seraddr));

seraddr.sin_family = AF_INET;

inet_pton(AF_INET, argv[1], &seraddr.sin_addr);

seraddr.sin_port = htons(8099);

if (0>connect(sockfd, (struct sockaddr*)&seraddr, sizeof(seraddr)))

{

printf("connect main -cli_b error: %s\n", strerror(errno));

return 1;

}

if (0>read(sockfd, tmpaddr_port_port, 128))

{

printf("read main -cli_b error: %s\n", strerror(errno));

return 1;

}

sscanf(tmpaddr_port_port, "%s %d %d", peer.ip, &peer.port, &port);

// close main socket

close(sockfd);

// create new p2p connect/listen socket

listenfd = socket(AF_INET, SOCK_STREAM, 0);

if (-1==listenfd)

{

printf("socket p2p connect -cli_b error: %s\n", strerror(errno));

return 1;

}

inet_pton(AF_INET, peer.ip, &seraddr.sin_addr);

seraddr.sin_port = htons(peer.port);

printf("Peer cli_a IP PORT: %s %d\n", peer.ip, peer.port);

// punch hole to cli_a

connect(listenfd, (struct sockaddr*)&seraddr, sizeof(seraddr));

printf("Punching hole is finished!\n");

// reuse socket's address

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &value, sizeof(value));

seraddr.sin_addr.s_addr = htonl(INADDR_ANY);

seraddr.sin_port = htons(port);

if (0>bind(listenfd, (struct sockaddr*)&seraddr, sizeof(seraddr)))

{

printf("bind p2p -cli_b error: %s\n", strerror(errno));

close(listenfd);

return 1;

}

if (0>listen(listenfd, 5))

{

printf("listen p2p -cli_b error: %s\n", strerror(errno));

close(listenfd);

return 1;

}

sockfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen);

if (-1==sockfd)

{

printf("accept p2p -cli_b error: %s\n", strerror(errno));

close(listenfd);

return 1;

}

len = read(sockfd, tmpbuf, 128);

if (0<len)

{

printf("%s", tmpbuf);

printf("\n");

}

len = write(sockfd, "I am b\n", strlen("I am b\n")+1);

if (0>=len)

{

printf("write p2p -cli_b error: %s\n", strerror(errno));

close(sockfd);

close(listenfd);

return 1;

}

close(sockfd);

close(listenfd);

printf("exit -cli_b\n");

return 0;

}

//result

Finally:

这下,有需要的朋友去p2p吧!!!

linux c tcp p2p的更多相关文章

  1. linux下TCP/IP及内核参数优化调优(转)

    Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等. 如下配置是写在sysctl.con ...

  2. Linux下TCP网络编程与基于Windows下C#socket编程间通信

    一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...

  3. Linux内核 TCP/IP、Socket参数调优

    Linux内核 TCP/IP.Socket参数调优 2014-06-06  Harrison....   阅 9611  转 165 转藏到我的图书馆   微信分享:   Doc1: /proc/sy ...

  4. linux上TCP connection timeout的原因查找

    linux上TCP connection timeout的原因查找 好久没有写文章了, 今天解决了一个网络连接超时的问题, 记录以备查看. 最近在线上nginx经常出现输出connection tim ...

  5. Linux中TCP wrapper的使用

    Linux中TCP wrapper的使用 tcpwrapper的目的是对那些访问控制功能较弱的服务提供访问控制功能要想了解访问控制就必须先知道服务监听的概念: 服务监听的两种方式: listen    ...

  6. Level-IP(Linux userspace TCP/IP stack)

    转自:github.com/saminiir/level-ip Level-IP is a Linux userspace TCP/IP stack, implemented with TUN/TAP ...

  7. 修改linux系统TCP连接数

    修改linux系统TCP连接数 centOS 6.x (1)vi /etc/sysctl.conf (2)添加参数 net.nf_conntrack_max = 655360 (3)sysctl -p ...

  8. Linux上TCP的几个内核参数调优

    Linux作为一个强大的操作系统,提供了一系列内核参数供我们进行调优.光TCP的调优参数就有50多个.在和线上问题斗智斗勇的过程中,笔者积累了一些在内网环境应该进行调优的参数.在此分享出来,希望对大家 ...

  9. 基于Linux的TCP网络聊天室

    1.实验项目名称:基于Linux的TCP网络聊天室 2.实验目的:通过TCP完成多用户群聊和私聊功能. 3.实验过程: 通过socket建立用户连接并传送用户输入的信息,分别来写客户端和服务器端,利用 ...

随机推荐

  1. 【winform】userControl刷新父窗体的datagridview

    1.ContextMenuStrip 获取右键控件名称 this.contextMenuScriptScore.SourceControl.Name; //当前控件名 2.radiobutton 分组 ...

  2. webpack proxyTable 跨域

    dev-server能在开发环境中生成一个本地服务器来实现代理 在vue-cli下 找的 dev下的 proxyTable: { '/':{ //前缀 target: 'http://www.exam ...

  3. Swift - use Array

    //数组声明 var arr0 = Array<Int>() var arr1 = Array<String>(count: 3, repeatedValue: "& ...

  4. .net core 2.x - 缓存的四种方式

    其实这些微软docs都有现成的,但是现在的人想对浮躁些,去看的不会太多,所以这里就再记录下 ,大家一起懒一起浮躁,呵呵. 0.基础知识 通过减少生成内容所需的工作,缓存可以显著提高应用的性能和可伸缩性 ...

  5. asp+SqlServer2008开发【第三集:win2winSSH远程连接—像连接Linux一样操作】

    1,参考:https://blog.csdn.net/flyingshuai/article/details/72897692 和https://blog.csdn.net/nijiayy/artic ...

  6. Kali Linux常用服务配置教程启动DHCP服务

    Kali Linux常用服务配置教程启动DHCP服务 通过前面的介绍,DHCP服务就配置好了.接下来,用户就可以使用该服务器来获取IP地址了.下面将对前面配置的服务进行测试. 1.启动DHCP服务 如 ...

  7. Java菜鸟浅谈OCR

    什么是OCR? 粗暴点说就是图片文本识别!正规点的说法就是:(Optical Character Recognition,光学电子识别) 最近公司开展新项目,考虑到实名认证这方面,然后还要上传身份证正 ...

  8. 错误解决记录-------------验证启动HDFS时遇到的错误

    主要解决验证启动HDFS时: 1) jps:bash: jps: command not found... 原因:主要是java/bin 环境变量没配置好. 解决办法: 在  ~/.bash_prof ...

  9. 前端性能优化 —— 添加Expires头

    简要:添加Expires头能有效的利用浏览器的缓存能力来改善页面的性能,能在后续的页面中有效避免很多不必要的Http请求,WEB服务器使用Expires头来告诉Web客户端它可以使用一个组件的当前副本 ...

  10. MFC版链表实现稀疏多项式相加减

    链表实现多项式运算(加减)MFC可视化版 题目 设计一个一元稀疏多项式简单计算器. 基本要求 (1)输入并建立两个多项式: (2)多项式a与b相加,建立和多项式c: (3)多项式a与b相减,建立差多项 ...