赞
踩
基于TCP的网络编程中,使用read/recv接收数据,使用write/send发送数据。sendto/recvfrom也可用于TCP数据传输
[1] 头文件
[2] 函数原型
ssize_t read(int fd, void *buf, size_t count);
功能:从描述符fd所指向的文件中读取count个字符到buf所指向的缓存区中
参数:
[3] 函数返回值:分几种情况
2)从设备文件中read数据
3)read用于套接字
[4] 补充:socket read中的阻塞和非阻塞
阻塞socket:read一直阻塞等待有数据到来返回,不管数据量多少返回其实际读取的字符数
非阻塞socket:不管socket接收缓冲区是否有数据都会立即返回,有数据返回实际读取的字符长度,没有数据返回-1,并errno为EWOULDBLOCK或者EAGAIN (表示应该设置为阻塞的)
[1] 头文件
[2] 函数原型
ssize_t write(int fd, void *buf, size_t length);
功能:把length个字节从buf所指缓冲区中写到描述符fd所指文件中
[3] 函数返回值:
成功:返回写入的字符数
失败:返回-1
阻塞和非阻塞返回值:
阻塞:与read不同(返回实际读取到的字符数),write只有在缓冲区足以放下整个buffer时才返回
非阻塞:返回能够放下的字节数,之后调用则返回-1,并errno = EAGAIN或EWOULDBLOCK
write成功
发送端和接收端缓存
对于每个socket都有自己的发送和接收缓冲区,不管TCP还是UDP
send buffer:已经发送到网络的数据依然需要暂存在send buffer中,只有收到对方的ack后,kernel才从buffer中清除这一部分数据,为后续发送数据腾出空间
receive buffer:接收端将收到的数据暂存在receive buffer中,自动进行确认。但如果socket所在的进程不及时将数据从receive buffer中取出,最终导致receive buffer填满,由于TCP的滑动窗口和拥塞控制,接收端会阻止发送端向其发送数据
write和read调用阻塞
write调用阻塞:一般来说,由于接收端进程从socket读数据的速度跟不上发送端进程向socket写数据的速度,最终导致发送端write调用阻塞
read调用阻塞:从socket的receive buffer中拷贝数据到应用程序的buffer中,read调用阻塞,通常是发送端的数据没有到达
[1] 头文件
[2] 实现
在C标准库中,assert是用宏来实现的,而不是函数
表达式:int assert(int expression);
功能:先计算表达式 expression ,如果其值为假为0,那么它先向stderr打印一条出错信息,然后通过调用 abort() 来终止程序运行
[3] 用法总结
int resetBufferSize(int nNewSize)
{
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
...
}
一次只检验一个条件,如果检验多个,断言失败无法直观判断是哪个条件出错
不能使用改变环境的语句
assert(i++ < 100)
先断言i是否小于100,再++
如果出错,比如i在执行之前就为100,那么i++这条命令就没有执行
[4] assert的缺点及避免
频繁调用会极大影响程序的性能,增加额外的开销
避免:在调试结束后,在assert.h头文件之前添加 #define NDEBUG 来禁止 assert 调用
#include <stdio.h>
#define NDEBUG
#include <assert.h>
2017.11.03
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。