srs 服务器在客户端断开连接后,服务器代码跟踪分析

最近有个疑问,当客户端主动断开连接的时候srs服务器是怎么主动断开的,gdb跟踪。

我发现的有两种情况:

1.客户端主动断开连接情况:客户端连接服务器后,一直ret = do_publishing(source, &trd);这个函数哪里等待(代码如下),

当客户端主动断开后,就继续运行后面的 trd.stop(); 这个trd.stop()才是服务器断开客户端退出线程的关键地方。


int SrsRtmpConn::publishing(SrsSource* source)
{
    int ret = ERROR_SUCCESS;

    if ((ret = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) {
        srs_error("check publish_refer failed. ret=%d", ret);
        return ret;
    }
    srs_verbose("check publish_refer success.");

    if ((ret = http_hooks_on_publish()) != ERROR_SUCCESS) {
        srs_error("http hook on_publish failed. ret=%d", ret);
        return ret;
    }

    bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost);
    if ((ret = acquire_publish(source, vhost_is_edge)) == ERROR_SUCCESS) {
        // use isolate thread to recv,
        // @see: https://github.com/ossrs/srs/issues/237
        SrsPublishRecvThread trd(rtmp, req,
            st_netfd_fileno(stfd), 0, this, source,
            client_type != SrsRtmpConnFlashPublish,
            vhost_is_edge);

        srs_info("start to publish stream %s success", req->stream.c_str());
        ret = do_publishing(source, &trd);

        srs_trace("===========>>>>>>>>>>will trd.stop");
        // stop isolate recv thread
        trd.stop();
    }
   
    // whatever the acquire publish, always release publish.
    // when the acquire error in the midlle-way, the publish state changed,
    // but failed, so we must cleanup it.
    // @see https://github.com/ossrs/srs/issues/474
    // @remark when stream is busy, should never release it.
    if (ret != ERROR_SYSTEM_STREAM_BUSY) {
        release_publish(source, vhost_is_edge);
    }

    http_hooks_on_unpublish();

    return ret;
}


2.客户端不正常退出后,服务器怎么断开连接的?

服务器会触发以写错误的信号 if (errno == EINTR),如下面代码

ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
    st_utime_t timeout)
{
  ssize_t n, rv;
  size_t nleft, nbyte;
  int index, iov_cnt;
  struct iovec *tmp_iov;
  struct iovec local_iov[_LOCAL_MAXIOV];

  /* Calculate the total number of bytes to be sent */
  nbyte = 0;
  for (index = 0; index < iov_size; index++)
    nbyte += iov[index].iov_len;

  rv = (ssize_t)nbyte;
  nleft = nbyte;
  tmp_iov = (struct iovec *) iov; /* we promise not to modify iov */
  iov_cnt = iov_size;

  while (nleft > 0) {
    if (iov_cnt == 1) {
      if (st_write(fd, tmp_iov[0].iov_base, nleft, timeout) != (ssize_t) nleft)
 rv = -1;
      break;
    }
    if ((n = writev(fd->osfd, tmp_iov, iov_cnt)) < 0) {
      if (errno == EINTR)
 continue;
      if (!_IO_NOT_READY_ERROR) {
 rv = -1;
 break;
      }
    } else {
      if ((size_t) n == nleft)
 break;
      nleft -= n;

后面的代码省略


然后发生接下来下面代码的:return ERROR_SOCKET_WRITE;

int SrsStSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
{
    int ret = ERROR_SUCCESS;
   
    ssize_t nb_write = st_writev(stfd, iov, iov_size, send_timeout);
    if (nwrite) {
        *nwrite = nb_write;
    }
   
    // On success a non-negative integer equal to nbyte is returned.
    // Otherwise, a value of -1 is returned and errno is set to indicate the error.
    if (nb_write <= 0) {
        // @see https://github.com/ossrs/srs/issues/200
        if (nb_write < 0 && errno == ETIME) {
            return ERROR_SOCKET_TIMEOUT;
        }
       
        return ERROR_SOCKET_WRITE;
    }
   
    send_bytes += nb_write;
   
    return ret;
}


最后也回到了1.客户端主动断开连接的这一样步骤,运行 trd.stop(); 退出线程


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值