首先是从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. 不固定高宽的 div 水平垂直居中

    <div class="father"> <div id="main"></div> </div> .fathe ...

  2. nodejs基础部分(一)

    前言 业余时间充实自我,入手学习了解一下传说中纯事件驱动/非阻塞的js架构 --nodejs 好记性不如烂笔头,本系列随笔用于整理记录学习nodejs过程中的心得 目录 nodejs简介 nodejs ...

  3. 【2017 Multi-University Training Contest - Team 2】Maximum Sequence

    [Link]:http://acm.hdu.edu.cn/showproblem.php?pid=6047 [Description] 给你一个数列a和一个数列b; 只告诉你a的前n项各是什么; 然后 ...

  4. Oracle中NVL、NVL2、DECODE函数的用法

    DECODE函数的用法:   DECODE(value,if1,then1,if2,then2,if3,then3,......,else),表示如果value的值等于if1时,DECODE函数的结果 ...

  5. [Angular] How to get Store state in ngrx Effect

    For example, what you want to do is navgiate from current item to next or previous item. In your com ...

  6. canvas和svg区别

    什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canvas 拥有多种绘制路径.矩形.圆形.字符以 ...

  7. BZOJ4044: [Cerc2014] Virus synthesis(回文树+DP)

    Description Viruses are usually bad for your health. How about fighting them with... other viruses? ...

  8. Java 学习(16):集合框架

    Java 集合框架 早在Java 2中之前,Java就提供了特设类.比如:Dictionary, Vector, Stack,  Properties 这些类用来存储和操作对象组. 虽然这些类都非常有 ...

  9. Android 手机插入电脑后提示“”ADB Interface"安装失败的问题

    安装ADB Interface 1. Android Studio开发时,如果在真机上测试并不是那么的顺利.直接将手机插入电脑,并不能识别.往往提示ADB Interface驱动未安装.如下图所示. ...

  10. ubuntu14中 memcached安装与使用

    第一步,先安装lib-event 下载lib-event  的包http://libevent.org/ 下载完之后,解压安装 ./configure –prefix=/usr (或 ./config ...