UDP协议点对点(P2P)通讯(或者说NAT穿越)实例



UDP协议点对点(P2P)通讯(或者说NAT穿越)实例。


【实验环境】

一个服务端Server,两个客户端:Client1和Client2 。Server和Client1在Linux系统上运行,Client2在Windows上运行。

Server端源代码:

#include 
#include   
#include   
#include   
#include   
#include   
  
int main(int argc, char *argv[])  
{  
    int 	i, n, len;
	int 	sockfd, port, sin_size;  
    struct 	sockaddr_in addr;   //服务器网络地址结构体  
    struct 	sockaddr_in remote_addr; //客户端网络地址结构体   
    char 	buf[1024];  //数据传送的缓冲区  
	
	if(argc != 3) 
	{ 
		fprintf(stderr,"Usage:%s ipaddr port\a\n",argv[0]); 
		return -1; 
	} 
	if((port = atoi(argv[2])) < 0) 
	{ 
		fprintf(stderr,"Usage:%s ipaddr port\a\n",argv[0]); 
		return -1; 
	} 
	
	bzero(&addr,sizeof(struct sockaddr_in)); 
	addr.sin_family=AF_INET; 
	addr.sin_addr.s_addr=inet_addr(argv[1]);//htonl(INADDR_ANY);  
	addr.sin_port=htons(port);
      
    /*创建服务器端套接字--IPv4协议,面向无连接通信,UDP协议*/  
    if((sockfd=socket(PF_INET, SOCK_DGRAM, 0)) < 0)  
    {    
        perror("socket");  
        return -1;  
    }  
   
    /* 将套接字绑定到网络地址上 */  
    if (bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr)) < 0)  
    {  
        perror("bind");  
        return -1;  
    }  

    sin_size=sizeof(struct sockaddr_in);  
    printf("waiting for a packet...\n");  
      
    if((len = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&remote_addr,&sin_size)) < 0)  
    {  
        perror("recvfrom");  
        return -1;  
    }
  
    printf("received packet from %s:%d\n", inet_ntoa(remote_addr.sin_addr), remote_addr.sin_port);  
	
    buf[len]='\0';  
    printf("%s\n",buf);  
	
    close(sockfd);

    return 0;  
}  


Client1的源代码:

#include 
#include 
#include
#include 
#include 
#include 
#include 
#include 


int main(int argc, char **argv)
{
	int sockfd, port, client2_port, sin_size;  
	struct sockaddr_in addr;
    struct sockaddr_in client2_addr;
	int  i, n;
	char buf[512];
	
	if(argc != 5) 
	{ 
		fprintf(stderr,"Usage:%s local_IPaddr local_port client2_IPaddr client2_port\a\n",argv[0]); 
		return -1; 
	} 
	
	if((port = atoi(argv[2])) < 0) 
	{ 
		fprintf(stderr,"Usage:%s local_IPaddr local_port client2_IPaddr client2_port\a\n",argv[0]); 
		return -1; 
	} 
	
	if((client2_port = atoi(argv[4])) < 0) 
	{ 
		fprintf(stderr,"Usage:%s local_IPaddr local_port client2_IPaddr client2_port\a\n",argv[0]); 
		return -1; 
	} 
	
    printf("This is a UDP client1\n");

	bzero(&addr,sizeof(struct sockaddr_in)); 
	addr.sin_family=AF_INET; 
	addr.sin_addr.s_addr=inet_addr(argv[1]);//htonl(INADDR_ANY);  
	addr.sin_port=htons(port);

    if ((sockfd=socket(AF_INET, SOCK_DGRAM, 0)) <0)
    {
        printf("socket error\n");
        return -1; 
    }

    if (bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr)) < 0)  
    {  
        perror("bind"); 
		close(sockfd); 
        return -1;  
    }  

	bzero(&client2_addr,sizeof(struct sockaddr_in));
    client2_addr.sin_family = AF_INET;
    client2_addr.sin_port = client2_port;  // 注意,在这里直接赋值,不要使用htons函数。(但是如果通讯失败,可以再用htons函数试试。)
    client2_addr.sin_addr.s_addr = inet_addr(argv[3]);

	i = 10;
    while (i--)
    {
		sprintf(buf, "client1: hi %d", i);
        n = sendto(sockfd, buf, strlen(buf), MSG_DONTWAIT, (struct sockaddr *)&client2_addr, sizeof(client2_addr));
        if (n < 0)
        {
            printf("sendto error\n");
            break;
        }

        sleep(1);
    }
	
	close(sockfd); 
   
    return 0;
}

Client2是TCP/UDP调试工具:

UDP协议点对点(P2P)通讯(或者说NAT穿越)实例_第1张图片


【测试方法】
1. 在远程机器上运行Server程序
参数是远程机器的本地IP和端口号(端口号随便写,只要不冲突就行),如下:
# ./server 48.89.13.216 5060
waiting for a packet...

2. 在本地机器运行Client2(即TCP/UDP调试工具)

创建个Server的UDP client:

UDP协议点对点(P2P)通讯(或者说NAT穿越)实例_第2张图片

向Server发送一串数据:

UDP协议点对点(P2P)通讯(或者说NAT穿越)实例_第3张图片

观察Server收到数据并显示出Client2的IP地址和端口:
# ./server 48.89.13.216 5060
waiting for a packet...
received packet from 140.246.118.101:62503
aa

3. 在远程机器上运行Client1程序

前两个参数是远程机器的本地IP地址和端口号,后两个参数是Client2的IP地址和端口号:
# ./client1  48.89.13.216 5687 140.246.118.101 62503
This is a UDP client1

4. 观察Client2已经收到Client1发来的数据

UDP协议点对点(P2P)通讯(或者说NAT穿越)实例_第4张图片


至此,UDP点对点(P2P)通讯实验成功!




你可能感兴趣的:(Linux,网络编程,windows,C++)