前言
在编程和网络通信中,write, read, recv, 和 send是用于数据传输的函数,它们通常在不同的编程语言和库中用于处理输入和输出。这些函数在功能上有一定的重叠。
recv和send特定于网络编程,位于socket.h库中
write和read通常用于文件 I/O 或低级的网络通信,位于unistd.h库中
在一般情况下,以下函数都用于阻塞模式。
文件 I/O 或低级的网络通信
write
用于写入数据到文件描述符(在 Unix-like 系统中,一切皆文件)。
通常用于文件 I/O 或低级的网络通信。
在 socket 编程中,write 函数用于向连接的 socket 发送数据。
read
用于从文件描述符读取数据。
通常用于文件 I/O 或低级的网络通信。
在 socket 编程中,read 函数用于从 socket 接收数据。
注意点:
write 和 read 通常用于面向连接的协议,因为它们保证数据的顺序和完整性。
在阻塞模式下,如果操作不能立即完成,调用会挂起(阻塞)进程的执行,直到操作完成。这意味着在数据被完全写入或读取之前,进程将不会继续执行后续的代码。
特定于网络编程
send
用于发送数据。
特定于网络编程,通常与 socket 一起使用。
send 函数向 socket 发送数据,通常用于阻塞模式的 socket。
recv
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
用于接收数据。
特定于网络编程,通常与 socket 一起使用。
recv 函数从 socket 中读取数据,通常用于阻塞模式的 socket。
参数意义
对于recv和send都是一样的
flags:一个选项标志,用于修改 recv 函数的行为。
0:默认值,表示正常接收数据。
MSG_OOB:接收带外数据(out-of-band data)。带外数据通常用于紧急数据的传输。
MSG_PEEK:窥视接收的数据。数据被读取但不从 socket 缓冲区中删除,后续的 recv 调用仍然可以看到这些数据。
MSG_WAITALL:等待足够的数据。通常与 len 参数结合使用,确保接收到完整的数据量,否则 recv 会一直等待。
MSG_DONTWAIT:非阻塞操作。如果 socket 是阻塞的,使用此标志会使得 recv 变为非阻塞,如果没有数据可读,recv 会立即返回,而不是等待。
返回值
write 返回写入的字节数,如果出错则返回 -1。
read 返回读取的字节数,如果到达文件末尾则返回 0,如果出错则返回 -1。
send 返回发送的字节数,如果出错则返回 -1。
recv 返回接收的字节数,如果远程主机关闭了连接则返回 0,如果出错则返回 -1。
不同点
数据传输的抽象级别:
write 和 read 操作通常在更高层次的抽象上,它们处理的是字节流,不需要关心底层的网络协议。
send 和 recv 操作在较低层次的抽象上,它们直接与网络协议(如 TCP 或 UDP)交互。
一个直接的体现就是send和recv可以通过指定flag的指来改变起函数的作用方式。
数据完整性:
write 通常将所有数据写入到文件或缓冲区中,而 read 从文件或缓冲区中读取数据,它们保证数据的完整性。
send 可能不会一次性发送所有数据,特别是在网络延迟或缓冲区满的情况下,可能需要分多次发送。recv 也可能分多次接收完整的消息。
非阻塞行为:
在非阻塞模式下,write 可能不会写入所有请求的数据,而是写入尽可能多的数据,然后立即返回。read 可能不会立即返回数据,而是返回一个错误,指示没有数据可读。
在非阻塞模式下,send 和 recv 也可能表现出类似的行为,但它们的行为还受到底层网络协议和系统调用实现的影响。