zoukankan      html  css  js  c++  java
  • client、server端编程

    首先是从main函数开发:



    int main(itn argc,char* argv[])
    {
    pthread_t thread;
    int count;
    int status;
            client_threads = CLIENT_THREADS;
    for(count = 0;count <client_threads,count++)
    {
    status = pthread_create(&thread,NULL,client_routine,(void*)count);
    if(status != 0)
    err_abort(status,"Create client thread");
    }
    status = pthread_mutex_lock(&client_mutex);
    if(status != 0)
    err_abort(status,"Lock client mutex");
    while(client_threads>0)
    {
    status = pthread_cond_wait(&clients_done,&client_mutex);
    if(status != 0)
    err_abort(status,"Wait for client to finish");
    }
    status = pthread_mutex_unlock(&client_mutex);
    if(status != 0)
    err_abort(status,"Unlock client mutex");
    printf("All client done ");
    tty_server_request(REQ_QUIT,1,NULL,NULL);
    return 0;
    }


    这个main函数在中间for循环中,调用pthread_create函数创建4个线程,传递给线程的数据位count(0,1,2,3).调用client_routine函数。


    void *client_routine(void *arg)
    {
    int my_number = (int)arg,loops;
    char prompt[32];
    char string[128],formatted[128];
    int status;
    sprintf(prompt,"Client 5d>",my_number);
    while(1)
    {
    tty_server_request(REQ_READ,1,prompt,string);
    if(strlen(string) ==0)
    break;
    for(loops =0;loops <4;loops++)
    {
    sprintf(formatted,"(%d#%d)%s",my_number,loops,string);
    tty_server_request(REQ_WRITE,0,NULL,formatted);
    sleep(1);
    }
    }
    status = pthread_mutex_lock(&client_mutex);
    if(status != 0)
    err_abort(status,"Lock client mutex");
    client_threads--;
    if(client_threads <= 0)
    {
    status = pthread_cond_signal(&clients_done);
    if(status != 0)
    err_abort(status,"Signale client done");
    }
    status = pthread_mutex_unlock(7client_mutex);
    if(status != 0)
    err_abort(status,"Unlock client mutex");
    return NULL;
    }

    pthread_cond_wait() 用于堵塞当前线程,等待别的线程使用pthread_cond_signal()pthread_cond_broadcast来唤醒它

     pthread_cond_wait() 必须与pthread_mutex 配套使用。pthread_cond_wait()函数一进入wait状态就会自己主动release mutex。当其它线程通过pthread_cond_signal()pthread_cond_broadcast。把该线程唤醒,使pthread_cond_wait()通过(返回)时,该线程又自己主动获得该mutex

      pthread_cond_signal函数的作用是发送一个信号给另外一个正在处于堵塞等待状态的线程,使其脱离堵塞状态,继续运行.假设没有线程处在堵塞等待状态,pthread_cond_signal也会成功返回。
      使用pthread_cond_signal一般不会有“惊群现象”产生,他最多仅仅给一个线程发信号。假如有多个线程正在堵塞等待着这个条件变量的话,那么是依据各等待线程优先级的高低确定哪个线程接收到信号開始继续运行。假设各线程优先级同样。则依据等待时间的长短来确定哪个线程获得信号。但不管怎样一个pthread_cond_signal调用最多发信一次。
      可是pthread_cond_signal在多处理器上可能同一时候唤醒多个线程,当你仅仅能让一个线程处理某个任务时。其他被唤醒的线程就须要继续 wait,并且规范要求pthread_cond_signal至少唤醒一个pthread_cond_wait上的线程。事实上有些实现为了简单在单处理器上也会唤醒多个线程. 
       另外。某些应用,如线程池,pthread_cond_broadcast唤醒所有线程,但我们通常仅仅须要一部分线程去做运行任务,所以其他的线程须要继续wait.所以强烈推荐对pthread_cond_wait() 使用while循环来做条件推断.

    在这里假设没有线程。则通知等待创建线程唤醒wait在此条件变量上的等待。


    上面所有代码:

    #include <pthread.h>
    #include <math.h>
    #include "errors.h"


    #define CLIENT_THREADS 4


    #define REQ_READ 1
    #define REQ_WRITE 2
    #define REQ_QUIT 3


    typedef struct request_tag
    {
    struct request_tag *next;
    int operation;
    int synchronous;
    int done_flag;
    pthread_cond_t done;
    char prompt[32];
    char text[128];
    }request_t;


    typedef struct tty_server_tag
    {
    request_t *first;
    request_t *last;
    int running;
    pthread_mutex_t mutex;
    pthread_cond_t request;
    }tty_server_t;


    tty_server_t tty_server = 
    {
    NULL,NULL,0,PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER
    };


    int client_threads;
    pthread_mutex_t client_mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t clients_done = PTHREAD_COND_INITIALIZER;


    void *tty_server_routine(void *arg)
    {
    static pthread_mutex_t prompt_mutex = PTHREAD_MUTEX_INITIALIZER;
    request_t *request;
    int operation,len;
    int status;
    while(1)
    {
    status = pthread_mutex_lock(&tty_server.mutex);
    if(status != 0)
    err_abort(status,"Lock server mutex");
    while(tty_server.first ==NULL)
    {
    status = pthread_cond_wait(&tty_server.request,&tty_server.mutex);
    if(status != 0)
    {
    err_abort(status,"Wait for request");
    }
    request = tty_server.first;
    tty_server.first= request->next;
    if(tty_server.first == NULL)
    {
    tty_server.last = NULL;
    }
    status = pthread_mutex_unlock(&tty_server.mutex);
    if(status != 0)
    err_abrort(status,"Unlock server mutex");
    operation = request->operation;
    switch(operation)
    {
    case REQ_QUIT:
    break;
    case REQ_READ:
    if(strlen(request->prompt)>0)
    printf(request->prompt);
    if(fgets(request->text,128,stdin)==NULL)
    request->text[0]='';
    len = strlen(request->text);
    if(len>0&&request->text[len-1]==' ')
    request->text[len-1]='';
    break;
    case REQ_WRITE:
    puts(request->text);
    break;
    default:
    break;
    }
    if(request->synchronous)
    {
    status = pthread_mutex_lock(&tty_server.mutex);
    if(status != 0)
    err_abort(status,"Lock server mutex");
    request->done_flag =1;
    status = pthread_cond__signal(&request->done);
    if(status != 0)
    err_abort(status,"Unlock server mutex");
    }else
    free(request);
    if(operation ==REQ_QUIT)
    break;
    }
    return NULL;
    }


    void tty_server_request(int operation,int sync,const char* prompt,char* string)
    {
    request_t *request;
    int status;


    status =pthread_mutex_lock(&tty_server.mutex);
    if(status != 0)
    err_abort(status,"Lock server mutex");
    if(!tty_server.running)
    {
    pthread_t thread;
    pthread_attr_t detached_attr;


    status = pthread_attr_init(&detached_attr);
    if(status != 0)
    err_abort(status,"Init attributes object");
    status = pthread_attr_setdetachstate(&detached_attr,PTHREAD_CREATE_DETACHED);
    if(status != 0)
    err_abort(status,"Set detach state");
    tty_server.running = 1;
    status = pthread_create(&thread,&detached_attr,tty_server_routine,NULL);
    if(status != 0)
    err_abort(status,"Create server");
    pthread_attr_destroy(&detached_attr);
    }
    request = (request_t*)malloc(sizeof(request_t));
    if(request ==NULL)
    errno_abort("Allocate Request");
    request->next = NULL;
    request->operation = operation;
    request->synchronous = sync;
    if(sync)
    {
    request->done_flag = 0;
    status = pthread_cond_init(&request->done,NULL);
    if(status != 0)
    err_abort(status ,"Init request condition");
    }
    if(prompt != NULL)
    strncpy(request->prompt,prompt,32);
    else 
    request->prompt[0]='';
    if(operation == REQ_WRITE &&string != NULL)
    strncpy(request->text,string,128);
    else
    request->text[0]='';
    if(tty_server.first == NULL)
    {
    tty_server.first = request;
    tty_server.last = request;
    }else
    {
    (tty_server.last)->next = request;
    tty_server.last= request;
    }
    status = pthread_cond_signal(&tty_server.request);
    if(status != 0)
    err_abort(status,"Wake server");
    if(sync)
    {
    while(!request->done_flag)
    {
    status = pthread_cond_wait(&request->done,&tty_server.mutex);
    if(status != 0)
    err_abort(status,"Wait for sync request");
    }
    if(operation == REQ_READ)
    {
    if(strlen(request->text)>0)
    strcpy(string,request->text);
    else 
    string[0]='';
    }
    status = pthread_cond_destroy(&request->done);
    if(status != 0)
    err_abort(status,"destroy request condition");
    free(request);
    }
    status = pthread_mutex_unlock(&tty-server.mutex);
    if(status != 0)
    err_abort(status,"Unlock mutex");
    }

  • 相关阅读:
    elasticsearch restful api 关于PUT与POST
    elasticsearch关于 PUT /index/type/id
    Windows性能计数器相关基础(一)
    打了断点但VS2010断点无效
    使程序以管理员权限运行(C++)
    CListCtrl控件使用方法总结 --很详细(一)
    AdjustTokenPrivileges(进程权限)
    四种方法实现VC枚举系统当前进程
    MFC个人笔记--创建属性表,并通过文件操作,保存属性表中用户的选择 的步骤
    学习笔记--MFC在滚动条窗口如何使所图的图形不产生偏移
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7044147.html
Copyright © 2011-2022 走看看