zoukankan      html  css  js  c++  java
  • linux c tcp p2p

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

    但是。。。

    今天分享一下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 ", 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 ", strerror(errno));

            close(listenfd);

            return 1;

        }

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

        {

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

            close(listenfd);

            return 1;

        }

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

        if (-1==sock_a)

        {

            printf("accept -server error: %s ", 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 ", 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 ", 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 ", tmpaddr_port);

        close(listenfd);

        printf("exit -server ");

        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> ");

            return 1;

        }

        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        if (-1==sockfd)

        {

            printf("socket -cli_a error: %s ", 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 ", strerror(errno));

            return 1;

        }

       

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

        {

            printf("read main -cli_a error: %s ", 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 ", 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 ", 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 ", strerror(errno));

            close(sockfd);

            return 1;

        }

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

        if (0>=len)

        {

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

            close(sockfd);

            return 1;

        }

        len = read(sockfd, tmpbuf, 128);

        if (0<len)

        {

            printf("%s", tmpbuf);

            printf(" ");

        }

        close(sockfd);

        printf("exit -cli_a ");

        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> ");

            return 1;

        }

        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        if (-1==sockfd)

        {

            printf("socket -cli_b error: %s ", 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 ", strerror(errno));

            return 1;

        }

       

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

        {

            printf("read main -cli_b error: %s ", 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 ", 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 ", peer.ip, peer.port);

        // punch hole to cli_a

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

        printf("Punching hole is finished! ");

       

        // 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 ", strerror(errno));

            close(listenfd);

            return 1;

        }  

        if (0>listen(listenfd, 5))

        {

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

            close(listenfd);

            return 1;

        }

       

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

        if (-1==sockfd)

        {

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

            close(listenfd);

            return 1;

        }

        len = read(sockfd, tmpbuf, 128);

        if (0<len)

        {

            printf("%s", tmpbuf);

            printf(" ");

        }

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

        if (0>=len)

        {

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

            close(sockfd);

            close(listenfd);

            return 1;

        }

        close(sockfd);

        close(listenfd);

        printf("exit -cli_b ");

        return 0;

    }

    //result

    Finally:

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

  • 相关阅读:
    SQL中的cast和convert用法示例
    SpendidCRM:在adminlayout中修改了视图上的字段后,用MyGeneration生成修改脚本
    [转]ASP.NET数据绑定方法
    商城 5051课 纪要
    .net判断用户是否已登录
    Jquery 监视按键,按下回车键触发某方法
    Sharepoint中三个强力的工具(WPManager, OSSEventManager, FriendlyQuery),另增清除已删除用户
    错误处理:此网页不允许使用基本类型"System.Web.UI.MasterPage”该类型未注册为安全类型
    MOSS页面显示“根级别上的数据无效”
    读取/设置超链接或图片类型栏的值
  • 原文地址:https://www.cnblogs.com/woodzcl/p/8125151.html
Copyright © 2011-2022 走看看