声明:原创,转载注明出处www.cnblogs.com/vestinfo/

write函数

头文件:#include <unistd.h>

原型:ssize_t write(int fd, const void* buf, size_t count);

参数:fd文件描述符;buf指向一段内存的指针;count想要写入fd的字节数。

返回值:正确返回实际写入fd的字节数;错误返回-1.

功能:将buf指向内存的count字节写入fd.

备注:理解这里实际写入的意思,一般实际写入即第三个参数count字节,但由于磁盘空间限制或中断等原因,
实际写入fd的字节数可能会<count,但是无论如何不会>count.

例子:

/*write例子 www.cnblogs.com/vestinfo*/
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
	int len;
	int fd;
	fd = open("test.txt", O_RDWR );

	char *buff_one = "abcdefgh";
	len = write(fd, buff_one, 256);
	printf("%d\n", len);

	char buff_two[6] = "abc";
	len = write(fd, buff_one, 256);
	printf("%d\n", len);

	buff_one = "abcdefgh";
	len = write(fd, buff_one, 2);
	printf("%d\n", len);

	buff_two[6] = "abc";
	len = write(fd, buff_one, 2);
	printf("%d\n", len);

	buff_one = "abcdefgh";
	len = write(fd, buff_one, strlen(buff_one));
	printf("%d\n", len);

	buff_two[6] = "abc";
	len = write(fd, buff_one, strlen(buff_two));
	printf("%d\n", len);

	return 0;
}

结果:

256
256
2
2
8
3

read函数

头文件:#include <unistd.h>

原型:ssize_t read(int fd, void *buf, size_t count);

参数:fd要从中读数据的描述符;读取的数据会存于buf指向的缓冲区;count希望调用一次读取的长度;

返回值:成功返回实际读取字节数(已到文件尾,返回0);错误返回-1;

功能:从fd中读取count字节数据存于buf中。

备注:如在到达文件尾还有30字节,而实际要求读100字节,则read返回30,下次调用read返回0.

例子:

 
/* read例子 www.cnblogs.com/vestinfo */
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
	int len;
	int fd;
	fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC );//不存在则创建,然后以可读写打开;存在则以可读写打开,将长度截短为0.

	char *buff_one = "abc";
	len = write(fd, buff_one, 24);
	printf("%d\n", len);

	close(fd);
	fd = open("test.txt", O_RDWR );
	char buff_two[6];
	len = read(fd, buff_two, 256);
	printf("%d\n", len);

	return 0;
}

结果:

24
24

如果将

close(fd);

fd = open("test.txt", O_RDWR );

这两行注释掉,则结果:

24

0

recvfrom  sendto

头文件:#include <sys/socket.h>

原型:ssize_t recvfrom(int sockfd, void* buff, size_t nbytes, int flags, struct sockaddr* from, socklent_t* addr_len);

        ssize_t sendto(int sockfd, void* buff, size_t nbytes, int flags, struct sockaddr* to, socklen_t addrlen);

参数:前三个参数通write read,flags置为0(后续讲解),from\to 存放对端地址结构,addrlen地址结构长度;

功能:recvfrom接收来自对端from的信息存于buff中;sendto发送信息buff到对端to。

备注:

(1)注意recvfrom最后一个参数是指向整数值的指针,sendto是一个整数值。(参考值——结果参数)

最后一个参数一般像下面一样给出:

socklen_t addr_len;
addr_len = sizeof(struct sockaddr_in); 
recvfrom(sockfd,buff,sizeof(buff),0,(struct sockaddr *)&addr,&addr_len);

 

(2)对于UDP,recvfrom返回0是可以接受的;而TCP的read返回0则表示对端关闭连接。

(3)如果不关心对端的协议地址,可以将recvfrom的最后两个参数置为空指针。

(4)recvfrom和sendto都可以用于TCP,但通常不这么做。

recv  send

头文件:#include <sys/socket.h>

原型:ssize_t recv(int sockfd, void* buff, size_t nbytes, int flags);

ssize_t send(int sockfd, const void* buff, size_t nbytes, int flags);

参数:前3个参数同read write的3个参数;flags要么是0要么是一些常值的逻辑或;常值及意义参阅头文件。

返回值:成功返回读写字节数,错误返回-1.

功能:比read write多了一个参数flags,可以理解为比read write操作更细化的函数,但仅用于套接字。

readv writev

头文件:#include <uio.h>

原型:ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);

         ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);

参数:filedes要在其上读写的标识符,iov指向iovec结构数组的指针,iovcnt数组元素个数。

返回值:成功返回读写字节数,错误返回-1.

功能:分散读(scatter read),集中写(gather write)。

例子:

/* 将三个独立的字符串一次写入终端。www.cnblogs.com/vestinfo */
#include <sys/uio.h> 
int main(int argc,char **argv) 
{ 
    char part1[] = "This is iov"; 
    char part2[] = " and "; 
    char part3[] = " writev test"; 

    struct iovec iov[3]; 
    iov[0].iov_base = part1; 
    iov[0].iov_len = strlen(part1); 
    iov[1].iov_base = part2; 
    iov[1].iov_len = strlen(part2); 
    iov[2].iov_base = part3; 
    iov[2].iov_len = strlen(part3); 
    writev(1,iov,3); 
    return 0; 
}


 

recvmsg sendmsg

头文件:#include <sys/socket.h>

原型:ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

         ssize_t sendmsg(int sockfd, msghdr *msg, int flags);

参数:sockfd要对其读写的文件描述符,flags参阅头文件。

返回值:成功返回读写字节数,出错返回-1.

功能:通用的I/O函数,即可以把所有read、readv、recv、recvfrom换成recvmsg;

可以把所有write、writev、send、sendto换成sendmsg.

备注:那么是如何做到替换的呢?关键在msghdr结构体,如下,

struct msghdr {
             void         *msg_name;       /* optional address */
             socklen_t     msg_namelen;    /* size of address */
             struct iovec *msg_iov;        /* scatter/gather array */
             size_t        msg_iovlen;     /* # elements in msg_iov */
             void         *msg_control;    /* ancillary data, see below */
             socklen_t     msg_controllen; /* ancillary data buffer len */
             int           msg_flags;      /* flags on received message */

};

5组I/O函数比较汇总

write read;writev readv;recv send;recvfrom sendto;recvmsg sendmsg五组I/O函数汇总

 

一般在UDP套接字中使用recvfrom sendto;在TCP套接字中使用read write.

 

参考:1、上面说到的头文件;2、《Unix Network Programing》.

相关文章:

  • 2022-12-23
  • 2021-10-02
  • 2021-08-21
  • 2021-12-06
  • 2021-08-05
  • 2021-09-07
  • 2021-08-01
  • 2021-08-04
猜你喜欢
  • 2022-12-23
  • 2022-01-17
  • 2021-06-26
  • 2022-12-23
  • 2021-09-28
相关资源
相似解决方案