zoukankan      html  css  js  c++  java
  • UDP客户端不用绑定吗IP和端口?

      书上都是这么说的,UDP客户端不用绑定IP和端口,操作系统会给它自动分配端口。。。。

      但是虽然没有显示绑定,但是操作系统却似乎做了些隐蔽的事情。

    首先,在客户端,fd = socket(AF_INET, SOCK_DGRAM, 0),然后就想在此fd下进行recvfrom是收不到对方(假设对方就是服务器吧)的消息是办不到的,其实想想也很容易明白,这是fd未和任何端口、IP产生关联要是这样都能收到消息,那真要乱套了。想要在没绑定的情况下受到服务器发来的消息,首先客户端得通过fd描述符首先向服务器发信息,然后这时在fd下进行阻塞recvfrom就能收到消息了,如果再在客户端上fd 1= socket(AF_INET, SOCK_DGRAM, 0),想在fd1 上进行recvfrom依然收不到消息,因为fd和服务器同过信,但fd1没有,所以fd1收不到,但是从fd1向服务器发消息没问题!所一总结一下就是,只有当已通过fd向服务器发送了消息时(并且已经发通了),才能在fd处收到服务器发回来的消息,但是向服务器发送消息就不需要。所以说操作系统在此做了些隐蔽的事情,当fd首先向服务器发消息时客户端自动选折IP和一个PORT与该fd关联了起来,(我觉得相当于背后还是绑定了一样)。而后面创建的fd1和之前的fd他们出客户端的PORT是不同的(我在服务器端检测了一下),所以通过fd向服务器发了消息但想在新建立的fd1下去recvfrom收不到消息。

      另外,只能对一个socket描述符绑定一次,不能绑定多次,除非前面已经将该描述符close了。

     反过来一个端口也只能被绑定到同一个socket描述符上,除非他们使用的不同的协议。

    下面有一些验证代码:

    client.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <strings.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #define PORT 50126
    #define MAXDATASIZE 100

    int main(int argc, char *argv[])
    {
    int fd1, numbytes;
    char recvbuf[MAXDATASIZE];
    char sendbuf[MAXDATASIZE];
    struct sockaddr_in server,self,rep;
    if ((fd1=socket(AF_INET, SOCK_DGRAM, 0))==-1){
    printf("socket() error\n");
    exit(1);
    }

    int server_ip1;

    bzero(&self,sizeof(self));
    self.sin_family = AF_INET;
    self.sin_port = htons(PORT);
    inet_pton(AF_INET, "10.10.1.103", (void*) &server_ip1);
            server.sin_addr.s_addr = server_ip1;

    bind(fd1,(struct sockaddr*)&self,sizeof(self));

    int server_ip;
    bzero(&server,sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    inet_pton(AF_INET, "10.10.1.103", (void*) &server_ip);
            server.sin_addr.s_addr = server_ip;

            socklen_t len;
             len=sizeof(struct sockaddr_in);
     printf("input message:");
             fgets(sendbuf,40,stdin);
    sendto(fd1,sendbuf,strlen(sendbuf),0,(struct sockaddr *)&server,len);
    printf("send already\n");
    int fd2=socket(AF_INET,SOCK_DGRAM,0);
    int i=bind(fd2,(struct sockaddr*)&self,sizeof(self));
    printf("%d\n",i);
    memset(sendbuf,0,sizeof(sendbuf));
    fgets(sendbuf,sizeof(sendbuf),stdin);
    sendto(fd2,sendbuf,strlen(sendbuf),0,(struct sockaddr *)&server,len);
    memset(recvbuf,0,sizeof(recvbuf));
    recvfrom(fd1,recvbuf,strlen(sendbuf),0,(struct sockaddr * ) &rep,&len);
    printf("A server give me:%s\n",recvbuf );
    recvfrom(fd2,recvbuf,strlen(sendbuf),0,(struct sockaddr * ) &rep,&len);
    printf("fd2 server give me:%s\n",recvbuf);

    return 0;
    }

    service.c

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<sys/types.h>
    #include<sys/socket.h>
    #include<errno.h>
    #include<arpa/inet.h>
    #include<netinet/in.h>
    #define  SERADDR "127.0.0.1"
    int main(int ar, char**argv) {
            int fd1, fd2;
            char *s;
            char ss[20];
            char port[7];
            int server_ip;
            char buf[1024];
            int len=sizeof(struct sockaddr);
            int sin_size = sizeof(struct sockaddr_in);
            struct sockaddr_in local_addr,other,other1;
            if (-1 == (fd1 = socket(AF_INET, SOCK_DGRAM, 0))) {
                    perror("fail to socket\n");
                    exit(0);
            }
            memset(buf,0,1024);
            memset(&local_addr,0,sizeof(struct sockaddr));
            local_addr.sin_family = AF_INET;
            local_addr.sin_port = htons(50126);

            inet_pton(AF_INET, "10.10.1.103", (void*) &server_ip);
            local_addr.sin_addr.s_addr = server_ip;


            if (bind(fd1, (struct sockaddr*) &local_addr, sizeof(struct sockaddr))
                            < 0) {
                    fprintf(stderr, "error:bind() error!\n");
        exit(-1);
            }


            recvfrom(fd1,buf,1023,0,(struct sockaddr*)&other,&len);
            in_port_t temport=ntohs(other.sin_port);
            sprintf(port,"%u",temport);
            printf("A,port =%s\n",port);
            printf("A ,client give me:%s\n",buf);
            memset(buf,0,sizeof(buf));

            recvfrom(fd1,buf,1023,0,(struct sockaddr*)&other1,&len);
            printf("B ,cLient give me:%s\n",buf);
            in_port_t temport1=ntohs(other1.sin_port);
            memset(port,0,sizeof(port));
            sprintf(port,"%u",temport1);


            printf("B,port=%s\n",port);
            //printf("hhhhhh\n");
            sendto(fd1,buf,strlen(buf),0,(struct sockaddr*)&other,sizeof(struct sockaddr_in));
            sendto(fd1,"OKOKOK",6,0,(struct sockaddr*)&other1,sizeof(struct sockaddr_in));

          
            return 0;

    }
                                                                                           

  • 相关阅读:
    分布式系统中的Session问题
    HotSpot VM运行时---命令行选项解析
    K大数查询
    [DarkBZOJ3636] 教义问答手册
    小朋友和二叉树
    [COCI2018-2019#2] Sunčanje
    小SY的梦
    [HDU6722 & 2019百度之星初赛四 T4] 唯一指定树
    [HDU6800] Play osu! on Your Tablet
    [NOI2007] 货币兑换
  • 原文地址:https://www.cnblogs.com/ymy124/p/2465599.html
Copyright © 2011-2022 走看看