linux下當連接配接斷開,還發資料的時候,不僅send()的傳回值會有反映,而且還會向系統發送一個異常消息,如果不作處理,系統會出BrokePipe,程式會退出,這對于伺服器提供穩定的服務将造成巨大的災難。為此,send()函數的最後一個參數可以設MSG_NOSIGNAL,禁止send()函數向系統發送異常消息
//中間的select就是為了偵測斷開後再次連接配接并二次send
int socket_send(async_socket_t* async_sock, uint8_t* buf, int len){
uint8_t* ptr = buf;
int left = len;
int rc;
while (left > 0) {
#ifdef __IOS__
rc = send(async_sock->fd, ptr, left, 0);
#else
rc = send(async_sock->fd, ptr, left, MSG_NOSIGNAL);
#endif
if(rc>0){
left -= rc;
ptr += rc;
}else if (rc<0) {
if (errno == EAGAIN) {
break;
} else if (errno == EINTR) {
continue;
} else {
printf("send step 1 failed\n");
return -1;
}
}
}
if(left>0){
printf("wait writeable");
fd_set writeset;
FD_ZERO(&writeset);
int max_fd = async_sock->fd + 1;
struct timeval timeout;
while(!async_sock->bstop && left>0){
timeout.tv_sec = 0;
timeout.tv_usec = 100*1000;
FD_SET(async_sock->fd, &writeset);
int ret = select(max_fd, NULL, &writeset, NULL, &timeout);
if( ret == 0){//TIMEOUT
continue;
}else if( ret < 0){
printf("select failed\n");
if(errno == EINTR){
continue;
}
return -1;
}
//writeable
#ifdef __IOS__
rc = send(async_sock->fd, ptr, left, 0);
#else
rc = send(async_sock->fd, ptr, left, MSG_NOSIGNAL);
#endif
if(rc>0){
left -= rc;
ptr += rc;
}else if (rc<0) {
printf("send step 2 failed\n");
return -1;
}
}
}
return len-left;
}