(一)发送时
当客户通过Socket提供的send函数发送大的数据包时,就可能返回一个EAGAIN的错误。该错误产生的原因是由于send 函数中的size变量大小超过了tcp_sendspace的值。tcp_sendspace定义了应用在调用send之前能够在kernel中缓存的数据量。当应用程序在socket中设置了O_NDELAY或者O_NONBLOCK属性后,如果发送缓存被占满,send就会返回EAGAIN的错误。
为了消除该错误,有三种方法可以选择:
1
.调大tcp_sendspace,使之大于send中的size参数
---no -p -o tcp_sendspace=
65536
2
.在调用send前,在setsockopt函数中为SNDBUF设置更大的值
3
.使用write替代send,因为write没有设置O_NDELAY或者O_NONBLOCK
(二)接收时
接收数据时常遇到Resource temporarily unavailable的提示,errno代码为11(EAGAIN)。这表明你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误,这个错误不会破坏socket的同步,不用管它,下次循环接着recv就可以。对非阻塞socket而言,EAGAIN不是一种错误。在VxWorks和Windows上,EAGAIN的名字叫做EWOULDBLOCK。其实这算不上错误,只是一种异常而已。
另外,如果出现EINTR即errno为4,错误描述Interrupted system call,操作也应该继续。
最后,如果recv的返回值为0,那表明对方已将连接断开,我们的接收操作也应该结束。
(三)以下是另一种解释
假如发送端流量大于接收端的流量(意思是epoll所在的程序读比转发的socket要快),由于是非阻塞的socket,那么send()函数虽然返回,但实际缓冲区的数据并未真正发给接收端,这样不断的读和发,当缓冲区满后会产生EAGAIN错误(参考man send),同时,不理会这次请求发送的数据.所以,
需要封装socket_send()的函数用来处理这种情况,该函数会尽量将数据写完再返回,返回
-1表示出错。在socket_send()内部,当写缓冲已满(send()返回-
1
,且errno为EAGAIN),那么会等待后再重试.这种方式并不很完美,在理论上可能会长时间的阻塞在socket_send()内部,但暂没有更好的办法.
这种方法类似于readn和writen的封装(自己写过,在《UNIX环境高级编程》中也有介绍)
[cpp] view plain copy
size_t socket_send(
int
sockfd,
const
char
*
buffer, size_t buflen)
size_t tmp;
size_t total
=
buflen;
const
char
*p =
buffer;
while
(
1
)
tmp
= send(sockfd, p, total,
0
);
if
(tmp <
0
)
//
当send收到信号时,可以继续写,但这里返回-1.
if
(errno ==
EINTR)
return
-
1
;
//
当socket是非阻塞时,如返回此错误,表示写缓冲队列已满,
//
在这里做延时后再重试.
if
(errno ==
EAGAIN)
usleep(
1000
);
continue
;
return
-
1
;
if
((size_t)tmp ==
total)
return
buflen;
total
-=
tmp;
p
+=
tmp;
return
tmp;
Android C++系列:Linux Socket编程(四)多路IO转接服务器
select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开 的文件描述符个数并不能改变select监听文件个数
Android C++ 系列:Linux Socket 编程(三)CS 模型示例
服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于 监听端口的状态,客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服 务器应答,服务器应答一个SYN-ACK段,客户端收到后从connect()返回,同时应答一个ACK 段,服务器收到后从accept()返回。
Android C++ 系列:Linux Socket 编程(二)网络套接字函数
socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描 述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调 用出错则返回-1。对于IPv4,domain参数指定为AF_INET。对于TCP协议,type参数指定为 SOCK_STREAM,表示面向流的传输协议。如果是UDP协议,则type参数指定为SOCK_DGRAM,表 示面向数据报的传输协议。protocol参数的介绍从略,指定为0即可。
Android C++ 系列:Linux Socket 编程(一)预备知识
为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运 行,可以调用以下库函数做网络字节序和主机字节序的转换。
ECS云服务器简单使用方法以及linux下c++socket搭建web服务器
ECS云服务器使用感受;关于linux下c++socket套接字搭建web服务器的坑:http响应体与跨域请求
开发平台 芯灵思Sinlinx A64内存: 1GB 存储: 4GB
开发板详细参数 https://m.tb.cn/h.3wMaSKm开发板交流群 641395230
阻塞:阻塞调用是指调用结果返回之前,当前进程程会被挂起(休眠)。