recv的返回值
a. 成功执行时,返回接收到的字节数。另一端已关闭则返回0。
b. 失败返回-1,errno被设为以下的某个值
EAGAIN:套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
EBADF:sock不是有效的描述词
ECONNREFUSE:远程主机阻绝网络连接
EFAULT:内存空间访问出错
EINTR:操作被信号中断
EINVAL:参数无效
ENOMEM:内存不足
ENOTCONN:与面向连接关联的套接字尚未被连接上
ENOTSOCK:sock索引的不是套接字
c. 当返回值是0时,为正常关闭连接;
数据发送过快问题
在使用非阻塞套接字的时候
服务器处理部分:
while(1)
{
recv();
if(ret==0)
{
close();
}
if(ret<0)
{
if(errno==EAGAIN)
{
add_mod();
}
}
else
{
sleep(5);
}
cout<<buf<<endl;
}
客户端:
send();
send();
send()
客户端到服务器的传输过程
这里用的是流式套接字:流式套接字的概念就是,数据会像水一样流动,当我们数据流太快,数据就会像水一样连接到一起,而不是像沙子一样,一颗一颗地分开;
客户端向服务器连续发送数据
当数据发送速度过快,会出现粘包;原因,流式套接字,数据发送过快,服务器套接字读缓冲区的数据未能及时通过recv取出,导致数据粘粘到一起;
比如:客户端连续发送数据,服务器的正在sleep,那么在网络正常的情况下,数据是被接收的(除非客户端写套接字缓冲区,或读套接字缓冲区已经满了),但是接收的数据是在套接字读缓冲区的。如果下一次通过recv接收的数据,如果服务器buf足够大,那么会将服务器在sleep期间的所有数据全部通过接收;
这里有个问题需要注意;\0这个字符;如果你想将接收到的数据打印显示;一定要注虽然数据粘合到一起;如果直接打印字符串会无法显示后面的数据;
原因如下:
如果从套接字缓冲区的通过recv接收到数据是:hello \0 world\0;
使用cout<<buf<<endl;
打印结果是 hello
而不是hello world;
粘包如何处理:
让服务器和客户端buf大小一致;
或则说在服务器设置固定大小的buf;每次recv只从缓冲区取指定大小的数据;