我们可以使用select函数重写http://www.cnblogs.com/nufangrensheng/p/3587962.html中的str_cli函数,这样服务器进程一终止,客户就能马上得到通知。早先那个版本的问题在于:当套接口上发生某些事件时,客户可能阻塞于fgets调用。新版本改为阻塞于select调用,等待要么标准输入可读,要么套接口可读。下图展示了调用select所处理的各种条件。

客户的套接口上的三个条件处理如下:

(i)如果对端TCP发送数据,那么该套接口变为可读,并且read返回一个大于0的值(即读入数据的字节数)。

(ii)如果对端TCP发送一个FIN(对端进程终止),那么该头接口变为可读,并且read返回0(EOF)。

(iii)如果对端TCP发送一个RST(对端主机崩溃并重新启动),那么该套接口变为可读,并且read返回-1,而errno中含有确切的错误代码。

新版本源代码:

#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h> int
max(int a, int b)
{
return(a >= b ? a : b);
} void
str_cli(FILE *fp, int sockfd)
{
int maxfdpl;
fd_set rset;
char sendline[4096], recvline[4096]; FD_ZERO(&rset);
for(;;)
{
FD_SET(fileno(fp), &rset);
FD_SET(sockfd, &rset);
maxfdpl = max(fileno(fp), sockfd) + 1;
if(select(maxfdpl, &rset, NULL, NULL, NULL) < 0)
{
perror("select");
exit(1);
} if(FD_ISSET(sockfd, &rset)) /* socket is readable */
{
if(readline(sockfd, recvline, 4096) == 0)
{
printf("str_cli: server terminated prematurely\n");
exit(1);
}
fputs(recvline, stdout);
} if(FD_ISSET(fileno(fp), &rset)) /* input is readable */
{
if(fgets(sendline, 4096, fp) == NULL)
return;
writen(sockfd, sendline, strlen(sendline));
}
}
}

调用select

我们只需要一个用于检查可读性的描述字集。该集合由FD_ZERO初始化,并用FD_SET打开两位:一位对应于标准I/O文件指针fp,一位对应于套接口sockfd。fileno函数把标准I/O文件指针转换为对应的描述字。select和poll只工作在描述字上。

计算出两个描述字中的较大值后,调用select。在该调用中,写集合指针和异常集合指针都是空指针。最后一个参数(时间限制)也是空指针,因为我们希望本调用阻塞到某个描述字就绪为止。

select使用实例——str_cli函数(修订版)的更多相关文章

  1. 函数与关系实例,函数运算与SQL,试验与关系元组

    函数是一个集合,它的每个元素都是二元组或多元组.例如 f = { (x, y) | x∈R & y∈R & y = 2x } ,g = { (x, y, z) | (x, y, z)∈ ...

  2. TCP回射客户程序:str_cli函数

    str_cli函数完成客户处理循环: 从标准输入读入一行文本,写到服务器上,读回服务器对该行的回射,并把回射行写到标准输出上 读入一行,写到服务器 fgets读入一行文本,writen把该行发送给服务 ...

  3. 使用select正确处理EOF的str_cli函数

    void str_cli(FILE *fp, int sockfd) { int maxfdp1, stdineof; fd_set rset; char buf[MAXLINE]; int n; s ...

  4. 使用select的str_cli函数的实现

    void str_cli(FILE *fp, int sockfd) { int maxfdp1; fd_set rset; char sendline[MAXLINE], recvline[MAXL ...

  5. MySQL之select查询、function函数

    一.select查询 //查询某张表所有数据 select * from temp; //查询指定列和条件的数据 //查询name和age这两列,age等于22的数据 ; //as对列重命名 //as ...

  6. go实例之函数

    1.可变参数 示例代码如下: package main import "fmt" // Here's a function that will take an arbitrary ...

  7. 深入理解group by 语句的执行顺序 from→where→group by→select(含聚合函数)

    由于之前没有对group by 语句的执行顺序(执行原理)做深入的了解,所以导致在实际应用过程中出现了一些问题.举个简单的粟子,比如一个表testA中的所有数据如下图: 我现在想从testA中查询us ...

  8. 非阻塞读和写:str_cli函数

    void str_cli(FILE *fp, int sockfd) { int maxfdp1, val, stdineof; ssize_t n, nwritten; fd_set rset, w ...

  9. TypeScript基础类型,类实例和函数类型声明

    TypeScript(TS)是微软研发的编程语言,是JavaScript的超集,也就是在JavaScript的基础上添加了一些特性.其中之一就是类型声明. 一.基础类型 TS的基础类型有 Boolea ...

随机推荐

  1. MySQL 之 多表查询

    一.多表联合查询 #创建部门CREATE TABLE IF NOT EXISTS dept ( did int not null auto_increment PRIMARY KEY, dname V ...

  2. [BZOJ4517][SDOI2016]排列计数(错位排列)

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1616  Solved: 985[Submit][Statu ...

  3. CodeForces - 1009E Intercity Travelling

    题面在这里! 可以发现全是求和,直接拆开算贡献就好了 #include<bits/stdc++.h> #define ll long long using namespace std; c ...

  4. Android签名有什么作用?

    应用程序升级:如果你希望用户无缝升级到新的版本,那么你必须用同一个证书进行签名.这是由于只有以同一个证书签名,系统才会允许安装升级的应用程序.如果你采用了不同的证书,那么系统会要求你的应用程序采用不同 ...

  5. [CSAcademy]Exponential Game

    题目大意: 有n堆石子,A和B两人轮流进行操作: 取走任意一堆石子,若这堆石子的个数是x个,那么可以放入x-1堆数量为0~x-1的石子. 不能操作者负. 思路: 将每一堆石子作为一个子游戏,将石子的数 ...

  6. [CodeForces-797F]Mice and Holes

    题目大意: 在一条直线上,有n个老鼠,m个洞. 每个老鼠i都有一个初始位置x[i]. 每个洞i都有一个固定位置p[i]和容量限制c[i]. 求所有老鼠都进洞的最小距离总和. 思路: 动态规划. 用f[ ...

  7. [CodeForces-332E]Binary Key

    题目大意: 给你两个字符串p和s,让你求出一个字典序尽量小的长度为k的01串密钥,能将p转化为s. 密钥的工作方式如下: 第i位是0,表示这一位无用: 第i位是1,表示这一位有用. 若密钥的长度比s短 ...

  8. java常用工具方法2

    /* * Copyright 2005 Joe Walker * * Licensed under the Apache License, Version 2.0 (the "License ...

  9. Fast-settling synchronous-PWM-DAC filter has almost no ripple

    An inexpensive way to implement high-resolution digital-to-analog conversion is to combine microcont ...

  10. 菜鸟学Java(二十)——你知道long和Long有什么差别吗?

    Java中数据类型分两种: 1.基本类型:long,int,byte,float,double2.对象类型:Long,Integer,Byte,Float,Double其他一切java提供的,或者你自 ...