zoukankan      html  css  js  c++  java
  • UDP并发服务器

    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28502731&id=3651271

    大多数UDP服务器程序是迭代运行的,服务器等待一个客户请求,读入这个请求,处理这个请求,送回其应答,再等待下一个客户请求。

    然而当客户请求的处理需要消耗过长的时间时,我们期望UDP服务器程序具有某种形式的并发性。

    当使用TCP时,服务器的并发处理得以简化的根源在于每个客户连接都是唯一的(不同的已连接套接字),标识每个客户连接的是一个唯一的套接字对。

    然而当使用UDP时,服务端通过同一个套接字和所有的客户端进行通信,当采用并发模式时,每一个子进程共享同一个UDP套接字,因此无法简单地绑定于一个客户并为其服务。

    有两种情况下可以使用并发的UDP服务器:

    1 读入一个客户请求并发送一个应答后,与这个客户不再有任何联系。在这种情形下,当一个UDP请求到达时,阻塞在epoll_wait调用上的父进程被唤醒,然后fork一个子进程去调用recv_from读取一个请求(一个完整的数据报),处理完该请求后再调用send_to发送回去。

    2  第二种UDP服务器与客户交互多个数据报。问题在于每个客户都是往服务器端的同一个的端口发送数据。并发服务器的每一个子进程如何正确区分每一个客户的数据报(涉及到进程的调度问题,如何避免一个子进程读取到不该它服务的客户发送来的数据报)。解决的方法是为每个客户创建一个的新的套接字,在其上bind一个临时端口,fork一个子进程使用该套接字发送对该客户的所有应答。这个办法要求客户查看服务器第一个应答的中的源端口号,并把本请求的后续数据报发送到该端口。

    废话少说,上代码!

    复制代码
    /server.c/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>
    
    
    
    
    
    int main(int argc,char *argv[])
    {
        int socket_fd, file_fd;
        struct sockaddr_in netaddr;
        struct sockaddr_in fromaddr;
        socklen_t len = sizeof(struct sockaddr);
    
        memset(&netaddr, 0, len);
        netaddr.sin_family = AF_INET;
        netaddr.sin_port = htons(5000);
        netaddr.sin_addr.s_addr = INADDR_ANY;
    
        if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
        {
            perror("Fail to create socket");
            return -1;
        }
        if (bind(socket_fd, (struct sockaddr*)&netaddr, sizeof(struct sockaddr)) == -1) {
            perror("bind");
            exit(1);
        }
    
        
        while (1) {
            char buf[100] = {};
            int ret = recvfrom(socket_fd, buf, 100, 0, (struct sockaddr *)&fromaddr, &len);
            if (ret == -1) {
                perror("recvfrom");
                exit(1);
            }
            printf("buf=%s
    ", buf);
            if (fork() == 0)
                break;
            printf("next==============
    ");
        }
        int sock2;
        if((sock2 = socket(AF_INET,SOCK_DGRAM,0)) < 0)
        {
            perror("child Fail to create socket");
            return -1;
        }
        if (sendto(sock2, "world", 5, 0, (struct sockaddr*)&fromaddr, len) == -1) {
            perror("child sendto");
            exit(1);
        }
    
    
        while (1) {
            char buf[100] = {};
            int ret = recvfrom(sock2, buf, 100, 0, (struct sockaddr *)&fromaddr, &len);
            if (ret == -1) {
                perror("child recvfrom");
                exit(1);
            }
            printf("child buf=%s
    ", buf);
        }
    
        close(socket_fd);
    
        return 0;
    }
    复制代码
    复制代码
    /*client.c*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>
    
    
    
    
    
    int main(int argc,char *argv[])
    {
        int socket_fd;
    
        struct sockaddr_in fromaddr;
        struct sockaddr_in servaddr;
        socklen_t len = sizeof(struct sockaddr);
    
       
    
        if((socket_fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
        {
            perror("Fail to create socket");
            return -1;
        }
       
        
        memset(&servaddr, 0, len);
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(5000);
        servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");;
    
        if (sendto(socket_fd, "hello", 5, 0, (struct sockaddr*)&servaddr, len) == -1) {
            perror("sendto");
            exit(1);
        }
        char buf[100] = {};
        if (recvfrom(socket_fd, buf, 100, 0, (struct sockaddr*)&fromaddr, &len) == -1) {
            perror("recvfrom");
            exit(1);
        }
        printf("recvfrom ip %s : %d
    ", inet_ntoa(fromaddr.sin_addr), ntohs(fromaddr.sin_port));
        printf("buf=%s
    ", buf);
    
        
        int i;
        for (i = 0; i < 10; i++) {
            char buf[100];
            int ret = sprintf(buf, "shit %d", i);
    
            if (sendto(socket_fd, buf, ret, 0, (struct sockaddr*)&fromaddr, len) == -1) {
                perror("sendto");
                exit(1);
            }
            printf("send ok
    ");
            sleep(1);
        }
    
        //sleep(5);
        close(socket_fd);
    
        return 0;
    }
    复制代码
  • 相关阅读:
    SAP OPEN UI5 Step 8: Translatable Texts
    SAP OPEN UI5 Step7 JSON Model
    SAP OPEN UI5 Step6 Modules
    SAP OPEN UI5 Step5 Controllers
    SAP OPEN UI5 Step4 Xml View
    SAP OPEN UI5 Step3 Controls
    SAP OPEN UI5 Step2 Bootstrap
    SAP OPEN UI5 Step1 环境安装和hello world
    2021php最新composer的使用攻略
    Php使用gzdeflate和ZLIB_ENCODING_DEFLATE结果gzinflate报data error
  • 原文地址:https://www.cnblogs.com/lidabo/p/14314598.html
Copyright © 2011-2022 走看看