字节流套接字上的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. 简单的闭包运算(Closure)演示程序

    /* * 该程序用于计算某个产生式的闭包 * RexfieldVon * 2013年8月9日16:01:38 */ #include <stdio.h> #include <stdl ...

  2. Servlet线程安全

    public class servletDemo1 extends HttpServlet { int i=0; public void doGet(HttpServletRequest reques ...

  3. NOI2015 程序自动分析 prog

    何等水题 某神犇仿关押罪犯的写法 却写挂了  然而实际上并不需要补集之类的 #include<iostream> #include<cstring> #include<c ...

  4. Unity3D 画线插件 Vectrosity_Simple2DLine

    Vectrosity是一个很方便的画线插件,用它我们可以画出2D,3D,贝塞尔,圆,椭圆等各种线条图案. :链接: http://pan.baidu.com/s/1pJjTFjt 密码: uesn 首 ...

  5. 基于MyBatis的数据库切分框架,可实现数据的水平切分和垂直切分。 http://www.makersoft.org

    https://github.com/makersoft/mybatis-shards MyBatis-Shards 专业的MyBatis数据库切分框架 MyBatis Shards简介 MyBati ...

  6. android之interpolator的用法详解

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

  7. 【开源java游戏框架libgdx专题】-01-libgdx介绍

    libgdx是一款开源的java游戏框架,而且还实现了Desktop/Android/BlackBerry/iOS/HTML5这些些平台的跨平台开发.官方网址:https://libgdx.badlo ...

  8. 设计模式UML图

    1.简单工厂模式 2.工厂模式 工厂模式与简单工厂模式的不同在于,每个操作类都有自己的工厂,而且把逻辑判断交给了客户端,而简单工厂的逻辑判断在工厂类里边,当增加新的操作类时,简单工厂需要修改工厂类,而 ...

  9. Django runserver show client ip

    get path of basehttp.py $ python >>> import site >>> site.getsitepackages() ['/usr ...

  10. css.day03.eg

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...