基于多进程服务器的在线购物

41 篇文章 0 订阅
17 篇文章 0 订阅

服务器

  • 原理过程已经在另一篇文章中说明,此处直接上代码
#include<stdio.h>
#include<pthread.h>
#include<signal.h>
#include<unistd.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<ctype.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>

#define SERVICE_PORT 8888
#define SERVICE_IP "127.0.0.1"


int consume();

void wait_child()//子进程回收函数
{
	waitpid(0,NULL,WNOHANG);//客户端退出后回收子进程
}
struct input
{
        int buf_num[8];//初始化用于写入来自客户端输入的数据buf_num
        char message[32];//初始化用于给客户发送提示信息
        int consume_num[7];//初始化传给客户端的每种纸币的数量情况
        int surplus_money;//初始化传给客户端剩余的钱
};

struct input *buf;//定义结构体指针变量,用于存放数据
int surplus_money;

int consume(int *my_money_num,int *consume_num)//第一个为传入参数,第二个为传出
参数
{
        //第一步:初始化剩余钱数,钱的类型,商品价格,自己拥有的钱
        int surplus_money = 0;
        int num = 0;
        int money[] = { 1,2,5,10,20,50,100 };
        int size = sizeof(money) / 4;
        int my_size = sizeof(my_money_num) / 4;
        int product_price = my_money_num[7];
        int i = 6;
        int my_money = 0;

        //第二步:计算自己的现金
        my_money = 100 * my_money_num[6] + 50 * my_money_num[5] + 20 * my_money_num[4] + 10 * my_money_num[3] + 5 * my_money_num[2] + 2 * my_money_num[1] + my_money_num[0];
        printf("你有【%d】元\n", my_money);
        printf("你的商品价格是:%d",product_price);

        //第三步:如果自己的钱>商品的价格,开始从高往底依次扣钱
        if (my_money >= product_price)
        {
                printf("开始扣钱。。。\n");
                while (1)
                {
                if ((product_price -= 100) >= 0 && (my_money_num[i]--) > 0)
                        {
                                consume_num[i]++;
                                continue;
                        }
                        else
                        {
                                product_price += 100;
                                break;
                        }
                }
                i--;
                while (1)
                {
                        if ((product_price -= 50) >= 0 && (my_money_num[i]--) > 0)
                        {
                                consume_num[i]++;
                                continue;
                                }
                        else
                        {
                                product_price += 50;
                                break;
                        }
                }
                i--;
                while (1)
                {
                        if ((product_price -= 20) >= 0 && (my_money_num[i]--) > 0)
                        {
                                consume_num[i]++;
                                continue;
                        }
                        else
                        {
                                product_price += 20;
                                break;
                                }
                }
                i--;
                while (1)
                {
                        if ((product_price -= 10) >= 0 && (my_money_num[i]--) > 0)
                        {
                                consume_num[i]++;
                                continue;
                        }
                        else
                        {
                                product_price += 10;
                                break;
                        }
                }
                i--;
                while (1)
                {
                if ((product_price -= 5) >= 0 && (my_money_num[i]--) > 0)
                        {
                                consume_num[i]++;
                                continue;
                        }
                        else
                        {
                                product_price += 5;
                                break;
                        }
                }
                i--;
                while (1)
                {
                        if ((product_price -= 2) >= 0 && (my_money_num[i]--) > 0)
                        {
                                consume_num[i]++;
                                continue;
                                }
                        else
                        {
                                product_price += 2;
                                break;
                        }
                }
                i--;
                while (1)
                {
                        if ((product_price -= 1) >= 0 && (my_money_num[i]--) > 0)
                        {
                                consume_num[i]++;
                                continue;
                        }
                        else
                        {
                                break;
                        }
                 }

                //第四步:计算消耗的钱,和剩余的钱
                int consume_money = 100 * consume_num[6] + 50 * consume_num[5] + 20 * consume_num[4] + 10 * consume_num[3] + 5 * consume_num[2] + 2 * consume_num[1] + consume_num[0];
                surplus_money = my_money - consume_money;


        }
        else
        {
                printf("你的钱不够!!!\n");
        }

        printf("欢迎下次光临\n");

        //第五步:返回出剩余的钱,用于发送给客户端
        return surplus_money;
        }

int main()
{
        struct sockaddr_in service_addr,client_addr;//定义服务器,客户端的结构>体地址名称
        buf = (struct input *)malloc(sizeof(struct input));//在堆区开辟空间

        char client_ip[16];//存放客户端的ip地址
        int num = 1;//表示客户端的连接数目
        pid_t pid;
        int connfp;//初始化连接套接字

        bzero(&service_addr,sizeof(service_addr));//清空service_addr

        //下面开始初始化服务器地址的各项信息
        service_addr.sin_family = AF_INET;
        service_addr.sin_port = htons(SERVICE_PORT);
        service_addr.sin_addr.s_addr = inet_addr(SERVICE_IP);
        //第一步:先利用socket函数产生一个监听套接字描述符
        int sockfp = socket(AF_INET,SOCK_STREAM,0);//协议选取ipv4
        if(sockfp == -1)
        {
                perror("socket error:");
                exit(1);
        }

        //第二步:利用bind函数将sockfp和service_addr绑定在一起,使sockfp这个用>于网络通信的文件描述符监听service_addr所描述的地址和端口号
        int bin = bind(sockfp,(struct sockaddr *)&service_addr,sizeof(struct sockaddr));
        if(bin == -1)
        {
                perror("bind error:");
                exit(1);
        }

        //第三步:声明sockfp处于监听状态,最多允许有128个客户端处于连接状态
        int list = listen(sockfp,128);
        if(list == -1)
        {
                perror("listen error:");
                exit(1);
        }

        while(1)//循环创建子进程
        {
                printf("begin to next connect...\n\n");
                int size = sizeof(client_addr);

                connfp = accept(sockfp,(struct sockaddr *)&client_addr,&size);//当有客户端发起连接时,服务器调用accept接受连接请求,然后阻塞,直到有下一个客户
端请求连接时再调用accept进行接受请求
                if(connfp == -1)
                {
                        perror("accept error:");
                        exit(1);
                }
                else if(connfp>0);//连接成功时会返回一个新的套接字描述符
                {
                        printf("\n\n[%d] new client is connected successfully!!!\n\n",num++);
                }

                printf("message is : client ip:%s,port:%d\n",inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip,sizeof(client_ip)),ntohs(client_addr.sin_port));//输出连接客户端的信息

                printf("begin to fork\n\n");
                pid = fork();
                if(pid < 0)
                {
                        perror("fork error");
                        exit(1);
                }
                else if(pid == 0)
                {
                        //子进程利用连接套接字connfp进行与客户端的数据交互
                        close(sockfp);
                        break;//子进程退出循环去执行下面的操作
                }
                else
                {
                        //父进程利用监听套接字sockfp等待客户端连接
                        close(connfp);
                        printf("开始回收子进程\n");
                        signal(SIGCHLD,wait_child);
                }
        }
        if(pid == 0)//子进程与客户端进行数据交互
        {
                printf("i am child,i am receiveing data from client...\n");
                while(1)//接受来自客户端的数据,通过计算,发送数据
                {
                        printf("开始read\n");
                        int r = read(connfp,buf->buf_num,sizeof(buf->buf_num));
                        if(r == -1)
                        {
                                perror("read error:");
                                exit(1);
                        }
                        else if(r == 0)
                        {
                                printf("read finish\n");
                        }
                                printf("开始执行consume\n");

                        buf->surplus_money = consume(buf->buf_num,buf->consume_num);
                        printf("surplus = %d\n",buf->surplus_money);
                        write(connfp,&buf->surplus_money,sizeof(buf->surplus_money));
                        sleep(1);

                        write(connfp,buf->consume_num,sizeof(buf->consume_num));
                        sleep(1);
                        strcpy(buf->message,"本次购物完成,是否继续购物?(y/n)");
                         write(connfp,buf->message,sizeof(buf->message));
                        sleep(1);
                }
        }
        return 0;
}

客户端

#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<ctype.h>

#define SERVICE_PORT 8888
#define SERVICE_IP "127.0.0.1"

struct input
{
        char message[32];//初始化用于写入数据的buf_in
        char answer[2];//初始化用于传出数据的buf_out
        int num[8];
        int consume_num[7];
        int surplus;
};
int main()
{
        struct sockaddr_in service_addr;//定义服务器结构体地址名称
        struct input *buf;//定义结构体指针变量,用于存放数据
        buf = (struct input *)malloc(sizeof(struct input));//在堆区开辟空
        pthread_rwlock_t rwlock;


        bzero(&service_addr,sizeof(service_addr));//清空service_addr

        //下面开始初始化服务器地址的各项信息
        service_addr.sin_family = AF_INET;
        service_addr.sin_port = htons(SERVICE_PORT);
        //service_addr.sin_addr.s_addr = htonl(SERVICE_IP);
        inet_pton(AF_INET,SERVICE_IP,&service_addr.sin_addr.s_addr);

        //第一步:先利用socket函数产生一个监听套接字描述符

        int sockfp = socket(AF_INET,SOCK_STREAM,0);//协议选取ipv4
        if(sockfp == -1)
        {
                perror("socket error:");
                exit(1);
        }
        printf("begin to connect\n\n");

        //第二步:利用connetc函数发起与服务器的连接

        int connfp = connect(sockfp,(struct sockaddr *)&service_addr,sizeof(struct sockaddr));//
        if(connfp == -1)
        {
                perror("bind error:");
                exit(1);
        }
        else if(connfp>0)//连接成功时会返回一个新的套接字描述符
        {
                printf("You have been connected with service successfully!!!\n\n");
                }
        while(1)//利用while循环给服务器写数据
        {
            memset(buf->num,0,sizeof(buf->num));
            printf("你已经开始购物!!!\n");
            printf("请按顺序输入:你的1元张数,2元张数,5元张数,10元张数,20元>张数,50元张数,100元张数,商品价格。。。\n");
            for(int i = 0;i<8;i++)
            {
                scanf("%d",&buf->num[i]);
            }

            printf("开始请求服务器...\n");
            write(sockfp,buf->num,sizeof(buf->num));

            read(sockfp,&buf->surplus,sizeof(buf->surplus));
            printf("你还剩[%d]元!\n",buf->surplus);
            sleep(1);

            read(sockfp,buf->consume_num,sizeof(buf->consume_num));
            printf("你的资金消耗情况如下:(顺序为:1元,2元,5元,10元,20元,50>元,100元)\n");
            for(int i = 0;i<7;i++)
            {
                printf("%d, \n",buf->consume_num[i]);
            }
            sleep(1);

            read(sockfp,buf->message,sizeof(buf->message));
            printf("message = %s\n",buf->message);

            scanf("%s", buf->answer);
                        printf("answer = %s\n", buf->answer);

                        if (strcmp(buf->answer, "n") == 0)
                        {
                                break;
                        }
        }
        return 0;
}

本人大部分代码开放免费,用于交流学习,有bug时还望指出,请勿直接抄袭,谢谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值