Linux 网络编程中的read和write函数正确的使用方式
字节流套接字上的read和write函数所表现的行为不同于通常的文件IO,字节流套接字上调用read和write输入或输出的可能比请求的数量少,然而这不是出错的状态,例如某个中端使read和write提前返回,这时就应该继续读和写而不是出错返回了,下面是unp中对read和write函数在socket中的使用的封装。
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
ssize_t readn(int fd,void* buff,size_t nbytes){
ssize_t nleft;
ssize_t nread;
char* ptr;
nleft=(ssize_t)nbytes;
ptr=(char*)buff;
nread=0;
while(nleft>0){
if((nread=read(fd,ptr,nleft))<0){
if(errno==EINTR){
nread=0;
}
else{
return -1;
}
}
else if(nread==0){ //read返回0代表读到EOF
break;
}
else{
nleft-=nread;
ptr+=nread;
}
}
return (nbytes-nread);
}
ssize_t writen(int fd,void* buff,size_t nbytes){
ssize_t nleft;
ssize_t nwrite;
char* ptr;
nleft=(ssize_t)nbytes;
nwrite=0;
ptr=(char*)buff;
while(nleft>0){
if((nwrite=write(fd,ptr,nleft))<=0){ //write返回0代表出错
if(nwrite<0&&errno==EINTR){
nwrite=0;
}
else{
return -1;
}
}
else{
nleft-=nwrite;
ptr+=nwrite;
}
}
return (nbytes);
}
//频繁使用read函数这个效率非常低
ssize_t readline(int fd,void* buff,size_t nbytes){
ssize_t n,rc;
char c,*ptr;
ptr=(char*)buff;
for(n=1;n<nbytes;++n){
again:
if((rc=read(fd,&c,1))==1){
*ptr++=c;
if(c=='\n')
break;
}
else if(rc==0)
return(n-1);
else{
if(errno==EINTR){
goto again;
}
return -1;
}
}
return (n);
}
//下面是一个改进版的但是这个版本使用了static变量,它是线程不安全的
#define MAXLINE 4096
static int read_cnt;
static char* read_ptr;
static char read_buf[MAXLINE];
//先从内核读一些数据到用户空间,在每次都从用户空间中读数据
static ssize_t myread(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;
else
read_ptr=read_buf;
}
read_cnt--;
*ptr=*read_ptr++;
return 1;
}
ssize_t readline(int fd,void* buff,size_t maxlen){
ssize_t n,rc;
char c,*ptr;
ptr=(char*)buff;
for(n=1;n<maxlen;++n){
if((rc=myread(fd,&c))==1){
*ptr++=c;
if(c=='\n')
break;
}
else if(rc==0){
*ptr='\0';
return (n-1);
}
else{
return -1;
}
}
*ptr='\0';
return n;
}
ssize_t readlinebuf(void **vptrtptr){
if(read_cnt)
*vptrvptr=read_ptr;
return read_cnt;
}
Linux 网络编程中的read和write函数正确的使用方式的更多相关文章
- linux网络编程中的shutdown()与close()函数
1.close()函数 int close(int sockfd); //返回成功为0,出错为-1 close 一个套接字的默认行为是把套接字标记为已关闭,然后立即返回到调用进程,该套接字不能再由cl ...
- linux网络编程中INADDR_ANY的含义
INADDR_ANY选项 网络编程中常用到bind函数,需要绑定IP地址,这时可以设置INADDR_ANY INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或&q ...
- 网络编程中的read,write函数
关于TCP/IP协议,建议参考Richard Stevens的<TCP/IP Illustrated,vol1>(TCP/IP详解卷1). 关于第二层面,依然建议Richard Steve ...
- linux网络编程中的超时设置
1 下面是在网上找到的资料,先非常的感谢. 用setsockopt()来控制recv()与send()的超时 在send(),recv()过程中有时由于网络状况等原因,收发不能预期进行,而设置收发超时 ...
- linux网络编程中的基本概念
int close(int fd)(假设是服务器端) close 关闭了自身数据传输的两个方向.close一个TCP套接字的默认行为是把该套接字标记成已关闭,然后立即返回到调用进程.该套接字描述符不能 ...
- linux网络编程中阻塞和非阻塞socket的区别
读操作 对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返 回.当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数.当 ...
- linux网络编程中需要注意的信号SIGPIPE
在调试cs时,s端循环收,c端循环发,s端意外崩溃后,c端自动退出,终端提示SIGPIPE导致c端退出.man 7 signal: SIGPIPE Term Broken pipe: write to ...
- Linux网络编程中tcp_server和tcp_client函数的封装
本文的主要目的是将server套接字和client套接字的获取,做一个简易的封装,使用C语言完成. tcp_server 服务器端fd的获取主要分为以下几步: 1.创建socket,这一步仅仅 ...
- Linux网络编程——I/O复用之poll函数
一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核 ...
随机推荐
- 解决打开MATLAB时出现“Waring:could not read file classpath.txt”,等问题
估计刚安装好的matlab是不会出现这个问题的,出现问题肯定是在某一次用360或者电脑管家清理垃圾之后才会出现这个问题. 首先声明我的matlab版本是matlab R2014a,下载链接:(额,网盘 ...
- NFC (Near Filed Communication)
NFC的用途:近场通信(Near Field Communication,NFC),又称近距离无线通信,是一种短距离的高频无线通信技术,允许电子设备之间进行非接触式点对点数据传输(在十厘米内)交换数据 ...
- java 通过eclipse编辑器用mysql尝试 连接数据库
注:本人学的是Oracle,用mysql连接数据库是一次尝试. 一.下载JDBC mysql驱动,导入jar包 我自己下载的是connector-java-6.0.6.jar,如下图所示,JD ...
- Javascript parseFloat、parseDouble类型转换,数值加减,四舍五入
<script language="JavaScript">var a = "0.11";var b = "0.2801";va ...
- android wear开发之:建立可穿戴设备的应用 - Building Apps for Wearables
注:本文内容来自:https://developer.android.com/training/building-wearables.html 翻译水平有限,如有疏漏,欢迎批评指教. 译:山人 建立可 ...
- 创建并在项目中调用SQLSERVER存储过程的简单示例
使用SQLSERVER存储过程可以很大的提高程序运行速度,简化编程维护难度,现已得到广泛应用.创建存储过程 和数据表一样,在使用之前需要创建存储过程,它的简明语法是: 引用: Create PROC ...
- TFS在项目中DevOps落地进程(下)
紧接上篇 TFS在项目中Devops落地进程(上) 再接着说TFS相关之前先插入一个番外篇,虽然跟TFS关系不大但跟DevOps关系很大,觉得有必要在此乱入一下. 番外篇--监控之Applicatio ...
- python调用c代码
Linux环境下使用python调用C的printf例子: #!/usr/bin/env python2.7 #-*- coding:utf-8 -*- from ctypes import * de ...
- python之socket模块
UDP client #!/usr/bin/env python2.7 #-*-coding:utf-8 -*- import socket s=socket.socket(socket.AF_INE ...
- Python mysqldb模块
#!/usr/bin/env python2.7 #-*- coding:utf8 -*- import os import sys import logging import MySQLdb fro ...