字节流套接字上的read和write函数所表现的行为不同于通常的文件IO

字节流套接字上调用read或write输入或输出的字节数可能比请求的数量少,然而这不是出错的状态

这个现象的原因在于内核中用于套接字的缓冲区可能已经达到了极限

此时需要的是调用者再次调用read或write函数,以输入或输出剩余的字节

ssize_t readn(int fd, void *vptr, size_t n)

/* include readn */
#include "unp.h" ssize_t /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr; ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
else
return(-1);
} else if (nread == 0)
break; /* EOF */ nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
/* end readn */ ssize_t
Readn(int fd, void *ptr, size_t nbytes)
{
ssize_t n; if ( (n = readn(fd, ptr, nbytes)) < 0)
err_sys("readn error");
return(n);
}

ssize_t writen(int fd, const void *vptr, size_t n)

/* include writen */
#include "unp.h" ssize_t /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr; ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0; /* and call write() again */
else
return(-1); /* error */
} nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
/* end writen */ void
Writen(int fd, void *ptr, size_t nbytes)
{
if (writen(fd, ptr, nbytes) != nbytes)
err_sys("writen error");
}

ssize_t readline(int fd, void *vptr, size_t maxlen)

/* include readline */
#include "unp.h" static int read_cnt;
static char *read_ptr;
static char read_buf[MAXLINE]; static ssize_t
my_read(int fd, char *ptr)
{ if (read_cnt <= 0) {
again:
if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
if (errno == EINTR)
goto again;
return(-1);
} else if (read_cnt == 0)
return(0);
read_ptr = read_buf;
} read_cnt--;
*ptr = *read_ptr++;
return(1);
} ssize_t
readline(int fd, void *vptr, size_t maxlen)
{
ssize_t n, rc;
char c, *ptr; ptr = vptr;
for (n = 1; n < maxlen; n++) {
if ( (rc = my_read(fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break; /* newline is stored, like fgets() */
} else if (rc == 0) {
*ptr = 0;
return(n - 1); /* EOF, n - 1 bytes were read */
} else
return(-1); /* error, errno set by read() */
} *ptr = 0; /* null terminate like fgets() */
return(n);
} ssize_t
readlinebuf(void **vptrptr)
{
if (read_cnt)
*vptrptr = read_ptr;
return(read_cnt);
}
/* end readline */ ssize_t
Readline(int fd, void *ptr, size_t maxlen)
{
ssize_t n; if ( (n = readline(fd, ptr, maxlen)) < 0)
err_sys("readline error");
return(n);
}

内部函数my_read每次最多读MAXLINE个字符,然后每次返回一个字符

readline函数本身的唯一变化是用my_read调用取代read

readlinebuf这个新函数能够展露内部缓冲区的状态,便于调用者查看当前文本行之后是否收到了新的数据

套接字地址结构是每个网络程序的重要组成部分,我们分配它们,填写它们,把指向它们的指针传递给各个套接字函数

有时我们把指向这些结构之一的指针传递给一个套接字函数,并由该函数填写结构内容

我们以引用形式来传递这些结构

而起将结构的大小作为另外一个参数来传递

当一个套接字函数需要填写一个结构时,该结构的长度也以引用形式传递,这样它的值也可以被函数更改

我们把这样的参数称为值-结果参数

套接字地址结构是自定义的,因为它们总是以一个标识其中所含地址之协议簇的字段开头

支持长度可变套接字地址结构的较新实现在开头还包含一个长度字段

它含有整个结构的长度信息

在表达格式(我们平时书写的格式,ascii字符串)

和数值格式(存放在套接字地址结构中的格式)

之间转换IP地址的2个函数:inet_pton和inet_ntop

TCP套接字为应用进程提供一个字节流,它们没有记录标记。从TCP套接字read的返回值可能比我们请求的数量少,但是这不代表发生了错误。

readn、write、readline的更多相关文章

  1. C#基础知识六之委托(delegate、Action、Func、predicate)

    1. 什么是委托 官方解释 委托是定义方法签名的类型,当实例化委托时,您可以将其实例化与任何具有兼容签名的方法想关联,可以通过委托实例调用方法. 个人理解 委托通俗一点说就是把一件事情交给别人来帮助完 ...

  2. [转载]C#委托和事件(Delegate、Event、EventHandler、EventArgs)

    原文链接:http://blog.csdn.net/zwj7612356/article/details/8272520 14.1.委托 当要把方法作为实参传送给其他方法的形参时,形参需要使用委托.委 ...

  3. 以 Console 方式运行、调试、编译 .Net 编写的 Windows 服务

    经常看到一些人在调试 Windows 服务时,很执著的在附加进程后调试!其实 .Net 编写的 Windows 应用程序,包括 Windows 服务都可以编译成 Console 程序!甚至于 ASP. ...

  4. Python学习笔记—Python基础1 介绍、发展史、安装、基本语法

    第一周学习笔记: 一.Python介绍      1.Python的创始人为吉多·范罗苏姆.1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言 ...

  5. python常用模块json、os、sys

    一.序列化 json & pickle 模块 json--用于字符串和Python数据类型间进行转换 pickle---用于python特有的类型和Python的数据类型间进行转换 json: ...

  6. 多线程中的锁系统(三)-WaitHandle、AutoResetEvent、ManualResetEvent

    本章主要介绍下基于内核模式构造的线程同步方式,事件,信号量. 阅读目录: 理论 WaitHandle AutoResetEvent ManualResetEvent 总结 理论 Windows的线程同 ...

  7. 七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL

    本节又带了一些常用的,却很难理解的问题,本节从文件上传功能的实现引出了线程使用,介绍了线程饥饿的解决方法,异常处理方法,了解RouteTable自定义路径 . 系列文章 七天学会ASP.NET MVC ...

  8. python 常用模块之os、sys、shutil

    目录: 1.os 2.sys 3.shutil 一.os模块 说明:os模块是对操作系统进行调用的接口 os.getcwd() #获取当前工作目录,即当前python脚本工作的目录路径 os.chdi ...

  9. C#对文件/目录的操作:Path、File、Directory、FileStream、StreamReader、StreamWriter等类的浅析

    以下类的命名空间都是:System.I/0; 一.Path:主要对文件路径的操作! 常用方法: String path=@"C:\a\b\c\123.txt"; 1-1.Path. ...

  10. 2016年11月28日--ADO.Net 查、插、删、改 小练习

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

随机推荐

  1. 《A First Course in Probability》-chaper1-组合分析-方程整数解的个数

    在概率论问题中求解基本事件.某个事件的可能情况数要涉及到组合分析. 而这一部分主要涉及到简单的计数原理和二项式定理.多项式定理. 我们从一个简单的实例入手. 方程的整数解个数: Tom喜欢钓鱼,一直他 ...

  2. Java调用R(一)_Rserve

    最近做项目涉及到R总结一些Java本地调用R和Java web项目中调用R的基本步骤 1.  R中安装Rserve包 2.  系统变量Path加上 C:\Program Files\R\R-3.0.1 ...

  3. 【java基础】--(3)javaIO详细阐释

    1.总的4类 字符:Reader 和Writer 字节:InputStream和OutputStream 2.Reader 六个子类BufferedReader, CharArrayReader, F ...

  4. Intellij调试debug

    先编译好要调试的程序. 1.设置断点 选定要设置断点的代码行,在行号的区域后面单击鼠标左键即可. 2.开启调试会话 点击红色箭头指向的小虫子,开始进入调试. IDE下方出现Debug视图,红色的箭头指 ...

  5. JVM调优之jstack找出发生死锁的线程

    1.执行死锁程序 2.执行 jstack -l 21733 | more 结果如下: 死锁程序: public static void main(String[] args) { // TODO Au ...

  6. Android给ListView设置分割线Divider样式

    给ListView设置分割线,只需设置如下两个属性: android:divider="#000" //设置分割线显示颜色 android:dividerHeight=" ...

  7. android之interpolator的用法详解

    Android:interpolator Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repea ...

  8. PHP数据结构预热:PHP的迭代器(转)

    迭代器有时又称光标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如list或vector)上遍访的接口,设计人员无需关心容器物件的内容. 各种语言实作Iterator的 ...

  9. golang中channel的超时处理

    并发中超时处理是必不可少的,golang没有提供直接的超时处理机制,但可以利用select机制来解决超时问题. func timeoutFunc() { //首先,实现并执行一个匿名的超时等待函数 t ...

  10. Android Studio下打jar包

    在我们使用Eclipse时,我们常常使用的第三方类库文件大多都是jar包形式,用起来很方便.但是jar包只能打包class文件,对于Android UI类库而言,我们常常需要打包资源文件,对于界面不多 ...