• [linux-socket]UNIX网络编程之UDP连接


    UDP属于非连接传输,因此不需要进行连接操作,直接可根据IP地址与端口发送数据

    服务器端

    char buf[1024];
            int i=0;
            int fd = socket(AF_INET,SOCK_DGRAM,0);
            struct sockaddr_in dest_addr;
    
            bzero(&dest_addr,sizeof(dest_addr));
            socklen_t addrlen;
            dest_addr.sin_family=AF_INET;
            dest_addr.sin_port=htons(10000);
            dest_addr.sin_addr.s_addr=INADDR_ANY;
            bind(fd,(struct sockaddr*)&dest_addr,sizeof(dest_addr));
    
            while (1) {
                    i++;
                    int ret = recvfrom(fd, buf, 1024, 0,(struct sockaddr*) &dest_addr, &addrlen);
                    if(ret < 0){
                            perror("recvfrom");
                            break;
                    }
    
                    printf ("%s,%d
    ", inet_ntoa (dest_addr.sin_addr), i);
          //获得地址dest_addr后,可用sendto向服务器发送数据
            }
            printf ("%s,%d
    ", inet_ntoa (dest_addr.sin_addr), i);

    服务器必须有固定的IP已经端口,因此必须使用bind函数把自身的套接字与固定端口绑定。

    由于服务器无法得知客户的IP以及端口,因此服务器必须首先使用UDP接收函数recvfrom()等待客户端发送数据。当客户端的数据到达后,客户端的地址信息被记录与dest_addr中,此时便可对客户传输数据

    客户端:

    char buf[1024];
            int i=0;
            struct sockaddr_in dest_addr;
    
            int sockfd = socket(AF_INET,SOCK_DGRAM,0);
            int len =  sizeof(buf);
    
            bzero(&dest_addr,sizeof(dest_addr));
            dest_addr.sin_family=AF_INET;
            dest_addr.sin_port=htons(10000);
            dest_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
            connect(sockfd,(struct sockaddr *)&dest_addr, sizeof(dest_addr));//如不连接,则系统为客户端随机分配端口
    
            while(i<10000)
            {
                    i++;
                    int ret = sendto(sockfd, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
                    if (ret < 0)
    
                    {
                            perror("write error");
                            break;
                    }
    
            }
            printf("send number:%d
    ",i);

    客户端必须事先知道服务器的IP地址以及端口,才能使用UDP函数sento()对服务器发送数据。

    客户端不需绑定端口。如不适用connect()和bind()函数,则系统自动给客户端随机分配一个端口作为发送端口使用,每次发送都使用不同的端口。如使用connect()设置后,则使用固定的端口发送数据。

    聊天室:不分服务器端和客户端,只需指明对方的IP和端口就可以聊天。

    #include <arpa/inet.h>
    #include <stdio.h>
    #include <string.h>
    #include <netinet/in.h>
    #include "pthread.h"
    
    char buf[1024];
    int fd;
    
    //thread for receive msg
    void* receiver(void* p){
            struct sockaddr_in dest_addr;
            int addrlen;
            while (1)
            {
                    int ret = recvfrom(fd, buf, 1024, 0,(struct sockaddr*) &dest_addr, &addrlen);
                    if(ret < 0)
                    {
                            perror("recvfrom");
                            break;
                    }
    
                    printf ("from %s:%d
    ", inet_ntoa (dest_addr.sin_addr),ntohs(dest_addr.sin_port));
                    printf("%s
    ",buf);
            }   
    }
    
    //main thread for send msg
    int main(int argc,char **argv)
    {
            if(argc!=4){
                    printf("usage:order IP port_dest port_local
    ");
                    return 0;
            }
    
            char buf[1024];
            fd = socket(AF_INET,SOCK_DGRAM,0);
            struct sockaddr_in dest_addr,my_addr;
    
            bzero(&dest_addr,sizeof(dest_addr));
            socklen_t addrlen;
            dest_addr.sin_family=AF_INET;
            dest_addr.sin_port=htons(atoi(argv[2]));
            dest_addr.sin_addr.s_addr=inet_addr(argv[1]);
    
            bzero(&my_addr,sizeof(my_addr));
            my_addr.sin_family=AF_INET;
            my_addr.sin_port=htons(atoi(argv[3]));
            my_addr.sin_addr.s_addr=INADDR_ANY;
            bind(fd,(struct sockaddr*)&my_addr,sizeof(my_addr));
    
            //init the thread
            pthread_t receiver_thread;
            if(0!=pthread_create(&receiver_thread, NULL, receiver, NULL))
                    printf("create thread failed
    ");
    
            while (1) {
                    gets(buf);
                    if(0==strcmp(buf,"exit")){
                            close(receiver_thread);
                            break;
                    }
                    int ret = sendto(fd, buf, 1024, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
                    if (ret < 0){
                            perror("write error");
                            break;
                    }
    
            }
    }

    通过写聊天室程序加深了对sendto和recvfrom两个UDP函数用法的理解。

    sendto(fd, buf, 1024, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));fd是自己的套接字,而不是发送目标的套接字。fd通过connect()或bind()可以与端口绑定,从而使用固定端口发送数据。如不适用此二函数,则使用随机端口发送。只要dest_addr正确设置了接受方的IP地址以及端口,即可发送数据。

    recvfrom(fd, buf, 1024, 0,(struct sockaddr*) &dest_addr, &addrlen);fd也是自己的套接字,不是接收方的套接字。也不需要事先设置接收方的地址就可以接受所有发送给自己的信息,dest_addr只是在接收到数据后记录发送方的地址而已。

  • 相关阅读:
    八、vue使用element-ui组件
    七、vue语法补充二(动态组件 & 异步组件、访问元素 & 组件、混入)
    oracle中使用sql语句生成10w条测试数据
    六、vue路由Vue Router
    五、vue状态管理模式vuex
    前端生态/工程化
    四、vue语法补充
    三、vue脚手架工具vue-cli的使用
    二、vue中组件的使用
    使用阿里云OSS上传文件
  • 原文地址:https://www.cnblogs.com/iyjhabc/p/3157314.html
Copyright © 2020-2023  润新知