社区导航

 

搜索
查看: 441|回复: 0

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

[复制链接]

1512

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2019-9-14 22:59 | 显示全部楼层 |阅读模式

【实验环境】

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

Server端源代码:

#include <stdio.h>
#include <string.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
  
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 <sys/types.h>
#include <sys/socket.h>
#include<pthread.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
 
 
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;
}

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

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

此帖出自RF/无线论坛


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐上一条 /4 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-2-26 02:07 , Processed in 0.075347 second(s), 15 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表