• 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;
    }
    复制代码
  • 相关阅读:
    直播流RTMP 知识
    XSSearch 说明文档保存
    网海茫茫,有你最暖
    实践中 XunSearch(讯搜)更新索引方案对比
    实践中 XunSearch(讯搜)的使用教程步骤
    留的住的叫幸福,流逝的叫遗憾
    百度API ; 很多有用的接口及公用 数据
    ecshop 模板开发总结
    jquery库和cityselect插 件的省市 级联
    PHP Excel 下载数据,并分页下载
  • 原文地址:https://www.cnblogs.com/lidabo/p/14314598.html
Copyright © 2020-2023  润新知