UNIX网络编程第三章——熟悉readn,writen函数,终端阻塞的一个博客

UNIX网络编程(套接字编程)

关于readn,writen 函数

/*
 * 日期:2021-8-8
 * 作者:2304768518@qq.com
 *
 * 用来熟悉readn,writen函数,测试的话
 * 现在好像不太会,得等到后面一点点
 *
 * #include <unistd.h>
 * int read(int fd,void* buf,size_t count)
 * 1.fd表示文件描述符,buf为读取数据的缓冲区,count是请求读取的字节数
 * 2.如果读取失败,返回-1,读取成功,返回读取的字符数并将文件的读写位置向后移
 *   如果已经读到文件末尾,返回0
 *
 * 关于readn函数:
 * 字节流套接字(TCP套接字)上的read和write函数所表现的行为不同于通常的文件I/O
 * 字节流套接字上调用read或write输入或输出的字节数可能比请求的字节数少,因为内核
 * 中用于套接字的缓冲区可能已经到达了极限,此时需要调用者再次调用read或write函数,
 * 以输入或输出剩余的字节
 *
 * ssize_t是有符号整型,在32位机器上等同与int,在64位机器上等同与long int
 * 有没有注意到,它和long数据类型有啥区别?其实就是一样的。
 * size_t 就是无符号型的ssize_t,也就是unsigned long/ unsigned int (在32位下)
 * ,不同的编译器或系统可能会有区别,主要是因为在32位机器上int和long是一样的。
 * 在64位没有测试,但是参见百度百科,size_t 在64位下是64位,那么size_t的正确定义应该是typedef unsigned long size_t。
 *
 */

#include "unp.h"

ssize_t readn(int fd,void *buff,size_t nbytes)
{
        ssize_t nleft=nbytes;//还需要读取的字符的数量
        ssize_t nread;//已经读取到的字符数量
        char *ptr=buff;//在这里做类型转换是为了将地址增加,也就是移动读写指针的位置

        //当还需要读取的字符数量等于0时,代表已经将所需要读取的字符全部读出了
        while(nleft>0){
                if((nread=read(fd,ptr,nleft))==-1){//代表读取内容失败
                        if(errno==EINTR){//Interrupted function,中断函数
                                //要再次读取文件夹中的内容
                                nread=0;
                        }else{
                                return(-1);
                        }
                }else if(nread==0){//代表读取到文件尾部
                        return (0);
                }
                //代表读取内容成功
                nleft-=nread;//还需要读取的字符数量减少
                ptr+=nread;//将指针向后移动,地址进行加减就可以
        }

        ptr=NULL;

        return (1);
}

//往一个文件中写东西
//write函数一般不会返回0,当第三个参数为0时,才会返回0
//当出错时,返回-1,否则返回写进去的字符数量
ssize_t writen(int fd,const void * buff,size_t nbytes)
{
        ssize_t nleft=nbytes;//需要写的东西的数量
        ssize_t nwrite;//已经写进去的数量
        const char *ptr=buff;//控制读写的指针

        while(nleft>0){
                if((nwrite=write(fd,buff,nleft))<=0){//程序出错了
                        if(nwrite<0&&errno==EINTR){
                                nwrite=0;
                        }else{
                                return(-1);
                        }
                }
                nleft-=nwrite;
                ptr+=nwrite;
        }

        ptr=NULL;

        return (nbytes);
}

int main(int argc,char ** argv)
{
        //打开一个文件,如果这个文件不存在就创建一个文件夹
        int fd=open("file",O_RDWR|O_CREAT);

        //往那个文件里面写内容
        if(write(fd,"hello world!",13)==-1){
                //errno("write error");
        }

        char str[13]="";
        int flag;

        //将某个文件中读写指针放在最前面
        if((lseek(fd,0,SEEK_SET)) ==  -1 ){
                printf("lseek,__LINE__\n");
        };

        //利用readn函数读取文件中的内容
        if((flag=readn(fd,str,13))==-1){
                printf("something error\n");
        }else if(flag==0){
                printf("读到文件末尾了\n");
        }else if(flag==1){
                printf("读取到的内容是:%s\n",str);
        }

        //再次将指针移动
        if(lseek(fd,0,SEEK_SET)==-1){
                printf("lseek,__LINE__\n");
        }

        read(fd,str,13);

        printf("利用read读到的东西是:%s\n",str);

        //打开文件file1
        int fd1=open("file1",O_RDWR|O_CREAT);
        if(writen(fd,"hello world!",13)==-1){
                printf("error\n");
        }else{
                read(fd1,str,13);
                printf("写进去的东西为:%s\n",str);
        }

}

关于终端阻塞的问题以及相关解决方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值