(十二)完善TcpConnection

1. SIGPIPE

SIGPIPE 默认行为是终止进程,在命令行程序中是合理的,但在网络编程中,这意味着如果对方断开连接而本地继续写入的话,会造成服务进程意外退出;
解决方法是在程序开始时忽略SIGPIPE;

class IgnoreSigPipe {
	public:
		IgnoreSigPipe() {
			::signal(SIGPIPE, SIG_IGN);
		}
};
IgnoreSigPipe initObj;

2. TcpNoDelay

此功能禁用Nagle 算法,避免连续发包出现延迟;

TcpConnection.h
+ void setTcpNoDelay();

底层实现:

::setsockopt(_sockfd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof optval);

3. 高低水平回调

高水平回调用于发送数据高于对方接受数据造成本地堆积,低水平回调用于本地处理数据过快造成等待发送数据;
两者类似PWM,前者可以通过回调停止读取数据,后者可以在回调中恢复相应的读取功能;

在发送时读取buffer 中的数据若无可调用低水平回调(writeCompleteCallback)

void TcpConnection::sendInLoop(const std::string &message) {
    _loop->assertInLoopThread();
    ssize_t nwrote = 0;
    if (!_channel->isWriting() && _outputBuffer.readableBytes() == 0) {
        nwrote = ::write(_channel->fd(), message.data(), message.size());
        if (nwrote >= 0) {
            if (implicit_cast<size_t>(nwrote) < message.size()) {
                LOG_TRACE << "I am going to write more data";
+            } else if (_writeCompleteCallback) {
+                _loop->queueInLoop(
                    std::bind(_writeCompleteCallback, shared_from_this()));
            }
        } else {
            nwrote = 0;
            if (errno != EWOULDBLOCK) {
                LOG_SYSERR << "TcpConnection::sendInLoop";
            }
        }
    }
    assert(nwrote >= 0);
    if (implicit_cast<size_t>(nwrote) < message.size()) {
        _outputBuffer.append(message.data() + nwrote, message.size() - nwrote);
        if (!_channel->isWriting()) {
            _channel->enableWriting();
        }
    }
}
void TcpConnection::handleWrite() {
    _loop->assertInLoopThread();
    if (_channel->isWriting()) {
        ssize_t n = ::write(_channel->fd(), _outputBuffer.peek(),
                            _outputBuffer.readableBytes());
        if (n > 0) {
            _outputBuffer.retrieve(n);
            if (_outputBuffer.readableBytes() == 0) {
                _channel->disableWriting();
+                if (_writeCompleteCallback) {
+                    _loop->queueInLoop(
                        std::bind(_writeCompleteCallback, shared_from_this()));
                }
                if (_state == kDisconnecting) {
                    shutdownInLoop();
                }
            } else {
                LOG_TRACE << "I am going to write more data";
            }
        } else {
            LOG_SYSERR << "TcpConnection::handleWrite";
        }
    } else {
        LOG_TRACE << "Connection is down, no more writing";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值