您当前的位置: 首页 > 

phymat.nico

暂无认证

  • 3浏览

    0关注

    1967博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

send返回值

phymat.nico 发布时间:2017-12-31 20:16:13 ,浏览量:3

[cpp] view plain copy
  1. int ret = this->peer().send_n(ack_msg, len, &time_zero_);  
  2.     switch (ret)  
  3.     {  
  4.         case 0:  
  5.             // peer closed  
  6.          
  7.             return -1;  
  8.         case -1:  
  9.             if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINPROGRESS)  
  10.             {  
  11.             //block  
  12.                 return 0;  
  13.             }  
  14.             else  
  15.             {  
  16.                 // abnormal error  
  17.             }  
  18.         default:  
  19.             if (ret != len)  
  20.             {  
  21.                             //no complex  
  22.                 return -1;  
  23.             }  
  24.             break;  
  25. if ((r = write(fd, offset, toSend)) offset += r;  
  26.             cq->bytes_out += r;  
  27.             if (c->offset == (off_t)c->mem->used - 1) {  
  28.                 chunk_finished = 1;  
  29.             }  

 

在Unix系统下,如果send、recv、write在等待协议传送数据时,socket被shutdown,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。此种情况应用就很难查出处理进程为什么退出。

 

SIGPIPE信号:

对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出。如果对SIGPIPE进行忽略处理,二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE.

处理方法:

在初始化时调用signal(SIGPIPE,SIG_IGN)忽略该信号(只需一次),SIGPIPE交给了系统处理。此时send、recv或write函数将返回-1,errno为EPIPE,可视情况关闭socket或其他处理    

SIGPIPE被忽略的情况下,如果服务器采用了fork的话,要收集垃圾进程,防止僵尸进程的产生,可以这样处理:  signal(SIGCHLD,SIG_IGN); 交给系统init去回收。这样子进程就不会产生僵尸进程了。

 

ACE中发送和接收超时都是基于select的

 

[cpp] view plain copy
  1. ssize_t  
  2. ACE::send_n_i (ACE_HANDLE handle,  
  3.                const void *buf,  
  4.                size_t len,  
  5.                int flags,  
  6.                const ACE_Time_Value *timeout,  
  7.                size_t *bt)  
  8. {  
  9.   size_t temp;  
  10.   size_t &bytes_transferred = bt == 0 ? temp : *bt;  
  11.   ssize_t n;  
  12.   ssize_t result = 0;  
  13.   int error = 0;  
  14.   int val = 0;  
  15.   ACE::record_and_set_non_blocking_mode (handle, val);  
  16.   for (bytes_transferred = 0;  
  17.        bytes_transferred  0; return a  
  18.       // ACE_ASSERT (result == 1);  
  19.       return result;  
  20.     }  

其它lighttpd:

[c-sharp] view plain copy
  1. // if  (len == 0 || (len fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {  
  2.         switch (errno) {  
  3.         case EAGAIN:  
  4. #if EWOULDBLOCK != EAGAIN  
  5.         case EWOULDBLOCK:  
  6. #endif  
  7.         case EINTR:  
  8.             /* we were stopped _before_ we had a connection */  
  9.         case ECONNABORTED: /* this is a FreeBSD thingy */  
  10.             /* we were stopped _after_ we had a connection */  
  11.             break;  
  12.         case EMFILE:  
  13.             /* out of fds */  
  14.             break;  
  15.         default:  
  16.             log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);  
  17.         }  
  18.         return NULL;  
  19.     }  
  20. fcgi  
  21. if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {  
  22.         if (errno == EINPROGRESS ||  
  23.             errno == EALREADY ||  
  24.             errno == EINTR) {  
  25.             if (hctx->conf.debug > 2) {  
  26.                 log_error_write(srv, __FILE__, __LINE__, "sb",  
  27.                     "connect delayed; will continue later:", proc->connection_name);  
  28.             }  
  29.             return CONNECTION_DELAYED;  
  30.         } else if (errno == EAGAIN) {  
  31.             if (hctx->conf.debug) {  
  32.                 log_error_write(srv, __FILE__, __LINE__, "sbsd",  
  33.                     "This means that you have more incoming requests than your FastCGI backend can handle in parallel."  
  34.                     "It might help to spawn more FastCGI backends or PHP children; if not, decrease server.max-connections."  
  35.                     "The load for this FastCGI backend", proc->connection_name, "is", proc->load);  
  36.             }  
  37.             return CONNECTION_OVERLOADED;  
  38.         } else {  
  39.             log_error_write(srv, __FILE__, __LINE__, "sssb",  
  40.                     "connect failed:",  
  41.                     strerror(errno), "on",  
  42.                     proc->connection_name);  
  43.             return CONNECTION_DEAD;  
  44.         }  
  45.     }  

 

 

 

 

    if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||                 fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0)

 

 

EAGAIN、EWOULDBLOCK、EINTR与非阻塞 长连接

EWOULDBLOCK用于非阻塞模式,不需要重新读或者写 EINTR指操作被中断唤醒,需要重新读/写 在Linux环境下开发经常会碰到很多错误(设置errno),其中EAGAIN是其中比较常见的一个错误(比如用在非阻塞操作中)。 从字面上来看,是提示再试一次。这个错误经常出现在当应用程序进行一些非阻塞(non-blocking)操作(对文件或socket)的时候。例如,以 O_NONBLOCK的标志打开文件/socket/FIFO,如果你连续做read操作而没有数据可读。此时程序不会阻塞起来等待数据准备就绪返 回,read函数会返回一个错误EAGAIN,提示你的应用程序现在没有数据可读请稍后再试。 又例如,当一个系统调用(比如fork)因为没有足够的资源(比如虚拟内存)而执行失败,返回EAGAIN提示其再调用一次(也许下次就能成功)。 Linux - 非阻塞socket编程处理EAGAIN错误 在linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,errno代码为11(EAGAIN),这是什么意思? 这表明你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误,这个错误不会破坏socket的同步,不用管它,下次循环接着recv就可以。 对非阻塞socket而言,EAGAIN不是一种错误。在VxWorks和Windows上,EAGAIN的名字叫做EWOULDBLOCK。 另外,如果出现EINTR即errno为4,错误描述Interrupted system call,操作也应该继续。 最后,如果recv的返回值为0,那表明连接已经断开,我们的接收操作也应该结束。

当客户通过Socket提供的send函数发送大的数据包时,就可能返回一个EGGAIN的错误。该错误产生的原因是由于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设置更大的值 

 

1.你自己的缓冲区满了,会返回EAGAIN。 2.你的没满,对方的缓冲区满了,肯定不关你事,可能会发送不成功,但是协议栈提供的系统调用,只管数据成功从你的缓冲区发出去,之后人家因为缓冲区满收不到数据,tcp自己有重传机制(参考Tcp/ip详解卷1)。

关注
打赏
1659628745
查看更多评论
立即登录/注册

微信扫码登录

0.0471s