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吧!!!

原文地址:https://www.cnblogs.com/woodzcl/p/8125151.html