1、read

-----------------------------------------------------------------------

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t nbyte);

-----------------------------------------------------------------------

read()函数是负责从fd中读取内容。当读成功时,read()返回实际所读的字节数,如果返回的值是0,表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。我们写一个自己的读函数:

int my_read(int fd,void *buffer,int length)
{
int bytes_left;
int bytes_read;
char *ptr; bytes_left=length; while(bytes_left>)
{
bytes_read = read(fd,ptr,bytes_read);
if (bytes_read < )
{
if(errno==EINTR)
bytes_read=;
else
return(-);
}
else if(bytes_read==)
break; bytes_left-=bytes_read;
ptr+=bytes_read;
} return(length-bytes_left);
}

2、write

-----------------------------------------------------------------------

#include <unistd.h>

ssize_t write(int fd, const void*buf,size_t nbytes);

-----------------------------------------------------------------------

write()函数将buf中的nbytes字节内容写入文件描述符fd,成功时返回写的字节数,失败时返回-1并设置errno变量。在网络程序中,当我们向套接字文件描述符写时有两可能:

1)write的返回值大于0,表示写了部分或者是全部的数据,这样我们用一个while循环来不停的写入,但是循环过程中的buf参数和nbyte参数得由我们来更新。也就是说,网络写函数是不负责将全部数据写完之后在返回的。

2)返回的值小于0,此时出现了错误,我们要根据错误类型来处理:

如果错误为EINTR表示在写的时候出现了中断错误。

如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

为了处理以上的情况,我们自己编写一个写函数来处理这几种情况。

int my_write(int fd,void *buffer,int length)
{
int bytes_left;
int written_bytes;
char *ptr; ptr=buffer;
bytes_left=length; while(bytes_left>)
{
/* 开始写*/
written_bytes=write(fd,ptr,bytes_left);
if(written_bytes<=) /* 出错了*/
{
if(errno==EINTR) /* 中断错误我们继续写*/
written_bytes=;
else /* 其他错误没有办法,只好撤退了*/
return(-);
} bytes_left-=written_bytes;
ptr+=written_bytes; /* 从剩下的地方继续写 */
} return();
}

3、recv & send

recv和send函数提供了和read和write差不多的功能,不过它们提供了第四个参数来控制读写操作。

-----------------------------------------------------------------------

#include <sys/types.h>

#include <sys/socket.h>

int recv(int sockfd,void *buf,int len,int flags);

int send(int sockfd,void *buf,int len,int flags);

-----------------------------------------------------------------------

前面的三个参数和一样,第四个参数可以是0或者是以下的组合:

|----------------------------------------------------------------------|

| MSG_DONTROUTE | 不查找表 |

| MSG_OOB | 接受或者发送带外数据 |

| MSG_PEEK | 查看数据,并不从系统缓冲区移走数据 |

| MSG_WAITALL | 等待所有数据 |

|----------------------------------------------------------------------|

MSG_DONTROUTE:是send函数使用的标志。这个标志告诉IP,目的主机在本地网络上面,没有必要查找表。这个标志一般用网络诊断和路由程序里面。

MSG_OOB:表示可以接收和发送带外的数据。关于带外数据我们以后会解释的。

MSG_PEEK:是recv函数的使用标志。表示只是从系统缓冲区中读取内容,而不清除系统缓冲区的内容,这样下次读的时候仍然是一样的内容。一般在有多个进程读写数据时可以使用这个标志。

MSG_WAITALL:是recv函数的使用标志。表示等到所有的信息到达时才返回。使用这个标志的时候recv会一直阻塞,直到指定的条件满足或者是发生了错误。

1)当读到了指定的字节时,函数正常返回。返回值等于len;

2)当读到了文件的结尾时,函数正常返回。返回值小于len;

3)当操作发生错误时返回-1,且设置错误为相应的错误号(errno)。

MSG_NOSIGNAL:is a flag used by send() in some implementations of the Berkeley sockets API.

This flag requests that the implementation does not to send a SIGPIPE signal on errors on stream oriented sockets when the other end breaks the connection. The EPIPE error is still returned as normal.

Though it is in some Berkely sockets APIs (notably Linux) it does not exist in what some refer to as the reference implementation, FreeBSD, which instead uses a socket option SO_NOSIGPIPE?.

对于服务器端,我们可以使用这个标志。目的是不让其发送SIG_PIPE信号,导致程序退出。

如果flags为0,则和read、write一样的操作。还有其它的几个选项,不过我们实际上用的很少。可以查看 Linux Programmer's Manual得到详细解释。

UNIX网络编程-recv、send、read、write之间的联系与区别的更多相关文章

  1. 【LINUX/UNIX网络编程】之简单多线程服务器(多人群聊系统)

    RT,Linux下使用c实现的多线程服务器.这个真是简单的不能再简单的了,有写的不好的地方,还希望大神轻拍.(>﹏<) 本学期Linux.unix网络编程的第四个作业. 先上实验要求: [ ...

  2. 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)

    RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三  多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...

  3. UNIX网络编程——客户/服务器心搏函数

    阅读此博客时,可以参考以前的博客<<UNIX网络编程--socket的keep-alive>>和<<UNIX网络编程--套接字选项(心跳检测.绑定地址复用)> ...

  4. 《Unix 网络编程》14:高级 I/O 函数

    高级 I/O 函数 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ...

  5. UNIX网络编程中的需要注意的问题

    字节流套接字上调用read或write,输入或输出的字节数可能比请求的数量少,这个现象的原因在于内核中用于套接字的缓冲区可能已经达到了极限.此时所需要的是调用者再次调用read或write函数.这个现 ...

  6. UNIX网络编程——UDP 的connect函数(改进版)

    上一篇我们提到,除非套接字已连接,否则异步错误是不会返回到UDP套接字的.我们确实可以给UDP套接字调用connect,然而这样做的结果却与TCP连接大相径庭:没有三次握手.内核只是检查是否存在立即可 ...

  7. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

  8. UNIX网络编程——并发服务器(TCP)

    在迭代服务器中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现. 网络服务器通常用fork来同时 ...

  9. 《Unix 网络编程》08:基本UDP套接字编程

    基本UDP套接字编程 系列文章导航:<Unix 网络编程>笔记 UDP 概述 流程图 recvfrom 和 sendto #include <sys/socket.h> ssi ...

随机推荐

  1. 【仿真】【modelsim】:verilog功能仿真流程

    一.编写verilog源文件,在diamond中编译.编写testbench文件.在diamond设置中将仿真工具设置为modelsim,运行仿真向导 二.自动进入modelsim, 编译全部 运行仿 ...

  2. Spring Bean配置

    Spring 是什么 •Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能. •Spring 是一个 IOC(DI) 和 ...

  3. iOS开发资源整理【01】

    一.网站 Code4App         开发者常用库分享网站 GitHub        git是一个优秀的分布式版本控制系统 stackoverflow    技术在线问答网站 CocoaChi ...

  4. Http协议访问DataSnap Rest 服务器

    用TIDHttp访问DataSnap Rest服务器,在服务器采用了用户验证的情况下,客户端需要注意下面的细节,否则不能正常连接. 假如服务器有如下的用户验证: procedure TSC.DSAut ...

  5. Cloudera-Manager修改集群的IP

    1.业务需求说明:由于公司网络进行了整改,随之而来的就是对应的ip网段发生了变化,其中我的hadoop的集群各主机的ip也相应的发生了改变,因此需要对各主机进行修改ip. 2.具体操作: 首先停止cd ...

  6. js中退出语句break,continue和return 比较 (转载)

    在 break,continue和return 三个关键字中, break,continue是一起的,return 是函数返回语句,但是返回的同时也将函数停止 首先:break和continue两个一 ...

  7. JS运动基础(四) 碰撞运动

    碰撞运动撞到目标点,速度反转无重力的漂浮Div速度反转滚动条闪烁的问题过界后直接拉回来 加入重力反转速度的同时,减小速度纵向碰撞,横向速度也减小横向速度小数问题(负数) <!DOCTYPE HT ...

  8. linux C之access函数(转-追梦的小鸟)

    access():判断是否具有存取文件的权限 相关函数    stat,open,chmod,chown,setuid,setgid表头文件    #include<unistd.h>定义 ...

  9. HDU 3966 Aragorn's Story

    题意:给一棵树,并给定各个点权的值,然后有3种操作:I C1 C2 K: 把C1与C2的路径上的所有点权值加上KD C1 C2 K:把C1与C2的路径上的所有点权值减去KQ C:查询节点编号为C的权值 ...

  10. truncate有外键约束的表,报ORA-02266处理。

    问题描述:当父表有子表的外键约束时,无法直接truncate父表.报ORA-02266: unique/primary keys in table referenced by enabled fore ...