固定端口的socket通信

在多台机器互联的场景下,可能会出现无法通信的情形,可能原因有:代码出错,地址出错,防火墙。对于防火墙的命令,后面会提及。
对于前两种错误debug就可以解决。如果这两种情况都不是,那么极有可能是防火墙的问题,我们可以通过wireshark来抓包进行分析。在wireshark抓包中,我们看到当fedora作为服务器接受到客户端的请求之后,给主机发回的信息会被host administratively prohibited。由此判断出是防火墙的问题。
对于防火墙拒绝了数据包,我们可以用两种方式处理:
1. 直接关闭防火墙,不推荐,但我们使用的是这个。
2. 通过在防火墙上添加允许通过的端口号来打开我们需要的端口。
所以,绑定端口的UDP通信十分必要。首先,我们需要知道的是
客户端所初始化的struct sockaddr_in 的端口、地址都是所发送到的服务器端的端口、地址。而服务器端所初始化的struct sockaddr_in 是指其本身监听的端口和地址。其次,如果想要固定端口号,对sendto()函数的参数有所要求,第一个参数为我们绑定了客户端地址、端口号的套接字,第五个参数则为赋值了服务器的端口号、地址的sockaddr_in。这里的一个小技巧是声明一个strcut sockaddr_in 变量,在对其初始化客户端端口号、地址并绑定过套接字后,再对此变量重新赋值为服务器的客户端、地址。服务器端会根据收到的数据包中的客户端端口号、地址回复。

下面给出固定端口号的客户端代码,因为服务端会根据客户端的端口号来回复。
这里我们只给出main函数,因为另外两个函数依然可用上一篇

linux下socket通信代码的开发及总结—UDP的内容
http://blog.csdn.net/success_by_choice/article/details/49826379

int main(int argc, char** argv){

    /* check args */
    if (argc !=2){
        printf("Usage: udp_request IP\n");
        exit(1);    
        }

    //创建两个线程
    pthread_t threadrecv,threadsend;
    void *retval;

    int port = 4600;
    int udp_descriptor; 

    struct sockaddr_in udpaddr; 

    //固定客户端端口号为4600
    bzero(&udpaddr,sizeof(udpaddr));
    udpaddr.sin_family=AF_INET;
    udpaddr.sin_port=htons(port);
    udpaddr.sin_addr.s_addr= inet_addr("192.168.1.3");//这里的地址应该为你客户端所用的ip地址

    int udp_descriptor = socket(AF_INET,SOCK_DGRAM,0);

    if(udp_descriptor == -1){
        printf("Create Socket Failed!\n");
        exit(1);    
    }
    if(bind(udp_descriptor,(struct sockaddr*)&udpaddr,sizeof(udpaddr)) == -1 ){
        printf("Server Bind Failed!\n");
        exit(1);    
    }

    udpaddr.sin_port=htons(port);
    inet_pton(AF_INET, argv[1], &udpaddr.sin_addr);

    struct argu_send args;
    args.adres =&udpaddr;
    args.sock = udp_descriptor;

    /*while(1)
    {
        send_msg(&args);
        get_msg(server_descriptor);
        sleep(3);
    }*/
    pthread_create(&threadsend,NULL,(void*)(&send_msg),&args);  

    pthread_create(&threadrecv,NULL,(void*)(&get_msg),&udp_descriptor);

    pthread_join(threadrecv,&retval);
    pthread_join(threadsend,&retval);

    return 0;   
}

值得一提的是,代码中用了多线程来实现,也可以不用线程,直接用循环来实现。代码中只需把注释掉的部分取消注释,并且去掉线程的部分即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值