首先是从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\n");

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]='\0';

len = strlen(request->text);

if(len>0&&request->text[len-1]=='\n')

request->text[len-1]='\0';

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]='\0';

if(operation == REQ_WRITE &&string != NULL)

strncpy(request->text,string,128);

else

request->text[0]='\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]='\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");

}

client、server端编程的更多相关文章

  1. Python的XMLRPC机制:实现跨进程间、client/server端通信

    SimpleXMLRPCServer模块式python语言的一个基于 xml 格式的进程间通信的基础框架. SimpleXMLRPCServer是一个单线程的服务器,这意味着,如果几个客户端同时发出多 ...

  2. client / server端用户的登录

    # 客户端 import socket import hashlib import json import os import struct sk = socket.socket() # 实例化 sk ...

  3. Linux下的C Socket编程 -- server端的继续研究

    Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...

  4. Linux下的C Socket编程 -- server端的简单示例

    Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...

  5. UDP也需要现有Server端,然后再有Client端

    UDP编程: DatagramSocket(邮递员):对应数据报的Socket概念,不需要创建两个socket,不可使用输入输出流. DatagramPacket(信件):数据包,是UDP下进行传输数 ...

  6. HBase 协处理器编程详解第一部分:Server 端代码编写

    Hbase 协处理器 Coprocessor 简介 HBase 是一款基于 Hadoop 的 key-value 数据库,它提供了对 HDFS 上数据的高效随机读写服务,完美地填补了 Hadoop M ...

  7. Socket编程, 在server端read()函数调用后显示错误:Transport endpoint is not connected (犯了低级错误)

    for(;;){ socklen_t len = sizeof(client_address); connfd = accept(listenfd, (struct sockaddr *)&c ...

  8. 从零开始学习Node.js例子四 多页面实现数学运算 续二(client端和server端)

    1.server端 支持数学运算的服务器,服务器的返回结果用json对象表示. math-server.js //通过监听3000端口使其作为Math Wizard的后台程序 var math = r ...

  9. 应用java多线程实现server端与多client之间的通信

    应用多线程来实现server与多线程之间的通信的基本步骤 1.server端创建ServerSocket,循环调用accept()等待client链接 2.client创建一个Socket并请求和se ...

随机推荐

  1. 11.Bean2Document-BEAN转document

    1. package com.glodon.gspm.adapter.plugin.common; import com.glodon.cloudt.tenancy.context.TenantCon ...

  2. div+css制作表格

    html: <div class="table"> <h2 class="table-caption">花名册:</h2> ...

  3. Atcoder At Beginner Contest 068 D - Decrease (Contestant ver.)

    D - Decrease (Contestant ver.) Time limit : 2sec / Memory limit : 256MB Score : 600 points Problem S ...

  4. angularjs 合并单元格

    Html: <table class="table table-striped"> <thead> <tr> <th>国家</ ...

  5. Direct2D 图形计算

    D2D不仅可以绘制,还可以对多个几何图形对象进行空间运算.这功能应该在GIS界比较吃香. 这些计算包括: 合并几何对象,可以设置求交还是求并,CombineWithGeometry 边界,加宽边界,查 ...

  6. Unity实现发送QQ邮件功能

    闲来无聊,用Unity简单实现了一个发送邮件的功能,希望与大家互相交流互相进步,大神勿喷,测试的是QQ邮件用到的是MailMessage类和SmtpClient类首先如果发送方使用的是个人QQ邮箱账号 ...

  7. Arch Linux下配置Samba

    本文记录笔者配置Samba的过程,供用于自用. sudo pacman -S samba sudo vim /etc/samba/smb.conf 添加以下内容 [global]    dns pro ...

  8. C# 依据KeyEventArgs与组合键字符串相互转换

    /// 快捷键相关的类 /// </summary> public static class HotKeyInfo { /// <summary> /// 依据KeyEvent ...

  9. 108.sqllite3(C语言数据库库)详解

    //创建数据库,插入表,生效 //创建数据库,插入表,生效 void create_database() { //数据库指针 sqlite3 *db=; //打开数据数据库,初始化指针 int res ...

  10. css实现水波纹效果

    1. HTML 代码: <div class="example"> <div class="dot"></div> < ...