首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

基于C/S架构的列队系统

2013-10-08 
基于C/S架构的排队系统一 问题来源2014腾讯研发工程师笔试题:请设计一个排队系统,能够让每个进入队伍的用

基于C/S架构的排队系统

一 问题来源

     2014腾讯研发工程师笔试题:请设计一个排队系统,能够让每个进入队伍的用户都能看到自己在 中所处的位置和变化。队伍可能随时有人加入和退出,当有人退出影响到用户的位置排名时需要即时反馈到用户。

二 思路

    排队即队列,要保证先进先出原则,队尾进,队头出。我把问题划分问两部分来解决:客户端和服务器端。客户端留给用户输入命令行,如“add x”,表示将用户x加入队列中,输入“rm y”表示将用户y从队列中删除,但是必须强调得是,加入某个用户必须在队尾实施插入操作,删除某个用户,此用户必须是队头用户,这是为了遵守队列“FIFO”原则,输入“show xx”表示显示用户xx的在队列中排名(位置)。

三 队列结构

基于C/S架构的列队系统

四 运行效果

客户端:

基于C/S架构的列队系统

服务器端:

基于C/S架构的列队系统

五 编程体会

     程序分为客户端与服务器端两部分,每部分都需要用到套接字编程,常用的操作有建立套接字、连接服务器、读写套接字等等。在服务器端,原本使用了“fork”创建子进程,在生成的子进程中对队列进行操作,如插入、删除结点,但是不断"fork"出的子进程有独立的地址空间,会使得队列无法连续生成,每个子进程都只能生成一个结点。所以回避了“fork”。这也是我调试了半天的经验。本系统使用了命令行的形式来对队列进行操作,能够完成题目的入队、出队和查看排名的要求,但实现的时候也有些不妥。比如如果某个用户离开队列,那么其他的用户怎样立即感知,这就不得不用“show XXX”这样的命令。所以还是有缺陷的,另外,gets函数比较危险,sscanf和sprintf函数不常用,但确实很有用。

六  代码

客户端:

/* * Copyright (C) 2013 wangzhicheng <2363702560@qq.com> *This program is free software; you can redistribute it and/or modify *it under the terms of the GNU Gernal Public License as published by *the Free software Foundation, version1.0 * Author: *     wangzhicheng <2363702560@qq.com> *     2013/10/6 * */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <pthread.h>#include <sys/socket.h>#include <signal.h>#include <netinet/in.h>#include <ctype.h>#define LEN 20/* * to define a Person structure and initialize * */typedef struct User {    char name[LEN];    unsigned int pos;}User;/* * the linked queue structure  * */typedef struct QueueNode {    User user;    struct QueueNode *next;}QueueNode;typedef struct LinkedQueue {    QueueNode *front;    QueueNode *rear;}LinkedQueue;pthread_mutex_t mutext;/* * to parse the command line  * @type: the type argument as add, rm and show  * @val: the value argument as username  * */int parse_cmdline(char *cmdline, char *type, char *val) {    int err = 0;    char *cp;    /*     * change the first '\n' into '\0'     * */    cp = strchr(cmdline, '\n');     if(cp) {*cp = '\0';    }    if(sscanf(cmdline, "%5s %12s", type, val) != 2) err = 1;    if(!strcmp(type, "add") && !strcmp(type, "rm") && !strcmp(type, "show")) {    err = 1;    }    return err;}/* * a function of queue system can add, remove or query  * @type: the type of cmdline as add, rm, show * @val: the username  * @resultstring: the result string which should return to the client socket * */void Do(LinkedQueue **Q, char *type, char *val, char *resultstring) {    QueueNode *p;            // point to the current node    QueueNode *pre;          // point to the previous of current node     QueueNode *r;            // point to the node should be deleted     int find;               // whether the node is located     if(strcmp(type, "add") == 0) {/* * to check whether check repeatedly * */find = 0;p = (*Q)->front;while(p) {    if(strcmp(p->user.name, val) == 0) {find = 1;break;    }    p = p->next;}if(find) {    strcpy(resultstring, "add repeatedly!\n");    return;}/* * to add a user to the queue system  * *//* * to create a new queue node  * */p = (QueueNode *)malloc(sizeof(QueueNode));if(!p) {         // Maybe this will hardly happen    fprintf(stderr, "memory error!\n");    exit(EXIT_FAILURE);}p->next = 0;User user;strncpy(user.name, val, 16);user.pos = 0;p->user = user;/* * to add the new queue node to the queue system * */if((*Q)->rear == NULL) {   // the queue system is empty    p->user.pos = 1;    (*Q)->front = p;    (*Q)->rear = p;}else {        // insert into the rear of queue system    p->user.pos = (*Q)->rear->user.pos + 1;    (*Q)->rear->next = p;    (*Q)->rear = p;}strcpy(resultstring, "add a new user to the queue system!\n");    }    /*     * to remove a node from the queue system     * */    else if(strcmp(type, "rm") == 0) {if(!(*Q)->front) {    // the queue system is empty    strcpy(resultstring, "remove failed, the queue system is empty!\n");    return;}else {    if(strcmp((*Q)->front->user.name, val)) {strcpy(resultstring, "You are not the head of queue!\n");return;    }    else {r = (*Q)->front;(*Q)->front = r->next;free(r);if(!(*Q)->front) (*Q)->rear = NULL;    }    strcpy(resultstring, "the head of queue has been deleted!\n");}/* * change the rank  * */p = (*Q)->front;while(p) {    p->user.pos--;    p = p->next;}    }    /*     * to show the rank      * */    else {if(!(*Q)->front) {    // the queue system is empty    strcpy(resultstring, "show failed, the queue system is empty!\n");        }        find = 0;p = (*Q)->front;while(p) {    if(strcmp(p->user.name, val) == 0) {sprintf(resultstring,"the rank is:%d", p->user.pos);find = 1;break;    }    else p = p->next;}if(!find) strcpy(resultstring, "show failed, no user!\n");    }}int main() {    /*     * create a empty queue system      * */    LinkedQueue *Q = (LinkedQueue *)malloc(sizeof(LinkedQueue));    Q->front = NULL;    Q->rear = NULL;    /*     * the socket fd is same the file descriptor     * */    int server_sockfd = -1;    int client_sockfd = -1;    int client_len = 0;    /*     * to define socket address     * */    struct sockaddr_in server_addr;    struct sockaddr_in client_addr;    /*     * to create a socket      * a socket contains domain, type and protocal     * */    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);//  bzero(&server_addr, sizeof(server_addr));  // to clear the server_addr    /*     * to initialize the socket address      * */    server_addr.sin_family = AF_INET;    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);    /*     * pay attention     * the port should be same with the port from client      * */    server_addr.sin_port = htons(9736);    /*     * to bind the sockect and its address      * */    bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));    /*     * to listen the port      * */    listen(server_sockfd, 5);    /*     * to ignore child processes which stop      * */    signal(SIGCHLD, SIG_IGN);    char msg[LEN];    char cmdline[LEN];    char type[5];    char val[12];    char resultstring[2 * LEN];       while(1) {client_len = sizeof(client_addr);        printf("server is waiting...\n");        /*  *  to accept a connect from a client socket          * */client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &client_len);        /*         * let the child process to deal with   * *//* * read data from socket  * */read(client_sockfd, &cmdline, sizeof(cmdline)); if(parse_cmdline(cmdline, type, val)) {    strcpy(resultstring, "cmdline contains error!\n"); }else {    Do(&Q, type, val, resultstring);    /*     * write the data to socket      * */    write(client_sockfd, &resultstring, sizeof(resultstring));}close(client_sockfd);    }    close(server_sockfd);    return 0;}



热点排行