• 【Socket】linux高性能网络服务程序


    1.mystery引入
      1)高性能的网络服务程序分为单线程重复式网络服务、多进程网络服务 、多线程网络服务、线程池网络服务和IO多路复用网络服务等
      2)单线程重复式是最基本的一种TCP服务模式,其实现简单,但是用户体验差,由于我前面日志中已经作过介绍,这里就不再赘述了
      3)多进程网络服务是利用Linux系统中的父子进程关系为多用户提供并发服务,基本理念是一个用户,启动一个服务进程。
       优点是方法通用,但是启动和关闭进程需要很大系统开销,不利于大量用户并发使用;
         另外父子进程间的数据共享与同步等具体实现会有一定困难。
      4)多线程网络服务类似于多进行网络服务模式,不同之处是前者是新启动一个线程,适用于商业环境中。
       5)线程池网络服务基本理念是:先创建一批资源,当有用户到来时,直接分配已创建好的资源
       目的是减少系统在频繁创建资源时的开销,优点是性能高效。
       6)IO多路复用是一种非阻塞的方式,与前面几种最大的不同是不会因为IO的操作而进入阻塞状态
         其调用Select的方式轮询各个套接字
         优点是系统开销小,不用创建和维护线程或进程队列,在Linux应用中比较多,常结合其它模式共同使用,以达到更好的效果。


    2.实例演示
       1)前面我已经演示过单线程重复式网络服务和IO多路复用了,所以这次只演示多进程网络服务、多线程网络服务和线程池网络服务
       2)采用C/S模式,设计一个统一的客户端,用3种不同的模式实现服务器端
       3)要求:在客户端,用户可以通过交互的方式,进行加、减、乖、除方面的运算设置,通过网络通信将计算参数传送到服务器端,然后服务器端完成具体的计算任务,并将结果返回。
       4)通信格式设计:客户端程序整体流程是收集用户的命令信息,打包发送给服务器端,服务器端通过解析数据包,识别出主要功能,同时执行运算,并将结果返回。
       5)对于多进程网络服务程序的设计,主要是调用系统的fork()函数,这里fork()函数的返回值很重要。
       6)多线程和多进程的原理类似。
       7)线程池架构
          1)功用上设计两个模块,一个服务主调度模块和一个线程服务模块。
          2)每个线程有两个状态:空闲状态和工作状态。
          3)每个线程均有一块属于自己的公共数据区域,存放两个变量,一个标记自身状态,一个对应客户端的套接字号。
          4)有新用户到来时,系统通过查找公共数据区域,判断当前是否有空闲线程,若有则为其分配服务线程。
          5)在线程服务的线程回调函数中,index对应于线程自身的索引号,通过该索引号,线程查找自身所属的公共数据区。


    3.效果演示
       1)多进程网络服务


       2)多线程网络服务      


       3)线程池网络服务

     



    4.源代码
       1)因为源代码是在linux下写的,日志是在win7下写的,复制过来有些文字乱码了,主要是因为编码方式不同,不过不影响代码的查看
       2)客户端
    //client.c
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #define PORT    5555
    #define SERVER_IP "127.0.0.1"
    typedef struct mathopt
    {
        int oprate;
        float value1;
        float value2;
    }mopt;
    void createopt(struct mathopt *pMp)
    {
        printf("please input operand one:");
        scanf("%f",&(pMp->value1));
        printf("please input operand two:");
        scanf("%f",&(pMp->value2));
    }
    void help()
    {
        printf("==================================================================
    ");
        printf("version:V1.0
    ");
        printf("author:mystery
    
    
    ");
        printf("%-12s %-12s
    ","Command","Fuction");
        printf("%-12s %-12s
    ","add","Adder computing");
        printf("%-12s %-12s
    ","minus","Minus computing");
        printf("%-12s %-12s
    ","multiply","Multiply computing");
        printf("%-12s %-12s
    ","divide","Divide computing");
        printf("%-12s %-12s
    ","hlep","Print help information");
        printf("%-12s %-12s
    ","quit","Exit the program");
        printf("==================================================================
    ");
    }
    main()
    {
        struct sockaddr_in serverAddr;
        int clientSocket;
        char sendbuf[200];
        char recvbuf[200];
        char command[20];
        if((clientSocket=socket(AF_INET,SOCK_STREAM,0)) < 0)
        {
            perror( "error: create socket!!!");
            return -1;
        }
        serverAddr.sin_family=AF_INET;
        serverAddr.sin_port=htons(PORT);
        serverAddr.sin_addr.s_addr=inet_addr(SERVER_IP);
        if(connect(clientSocket,( struct sockaddr * )&serverAddr,sizeof(serverAddr)) < 0)
        {
            perror("error: connect remote server !!!");
            exit(1);
        }
        printf("infor: connect with destination host........[ok]
    ");
        while(1)
        {
            printf("Input your World:>");
            scanf("%s",command);
            struct mathopt mp;
            if(strcmp(command,"add") == 0)
            {
                createopt(&mp);
                mp.oprate = 0;
            }
            else if(strcmp(command,"minus") == 0)
            {
                createopt(&mp);
                mp.oprate = 1;
            }
            else if(strcmp(command,"multiply") == 0)
            {
                createopt(&mp);
                mp.oprate = 2;
            }
            else if(strcmp(command,"divide") == 0)
            {
                while(1)
                {
                    createopt(&mp);
                    if(mp.value2 == 0)
                    {
                        printf("warning: Dividend can not be 0!!!!!
    ");
                    }
                    else
                    {
                        break;
                    }
                }
                mp.oprate = 3;
            }
            else if(strcmp(command,"help") == 0)
            {
                help();
                continue ;
            }
            else if(strcmp(command,"quit") == 0)
            {
                mp.oprate = 4;
            }
            else
            {
                printf("error: can't identify your input !!!
    ");
                continue ;
            }
            send(clientSocket,(char *)&mp,sizeof(mp),0);
            if(mp.oprate == 4)
            {
                break;
            }
            recv(clientSocket,recvbuf,200,0);
            printf("the result is: %s
    ",recvbuf);
        }
        close(clientSocket);
        return 0;
    }
     
     
      3)多进程服务端
       //multiprocesserver.txt,见附件
     

       4)多线程网络服务端
       //multithreadserver.txt,见附件
     

       6)线程池网络服务端
       //poolserver.txt,见附件
     
     
     

    本文出自 “成鹏致远” 博客,请务必保留此出处http://infohacker.blog.51cto.com/6751239/1155167

  • 相关阅读:
    NullPointerException
    面试oracle 经常问的一个问题- 事务
    python 之 import、from、as 关键字的 白话 解释与例子
    python 学习 之 第二章(条件、循环和其他语句)
    python学习 之 第一章 (简单例子与常用数据类型)
    python中常用函数含义记录
    python 2 版本中的input() 和 raw_input() 函数的比较
    字符串处理关键字str 和 repr
    文件操作-一个可以直接复制文件数据的小程序
    C语言 32个关键字
  • 原文地址:https://www.cnblogs.com/lcw/p/3159504.html
Copyright © 2020-2023  润新知