问题

     现场无法接收到海康的国标报文,可以接收到自己创建的服务器报文,通过抓包是可以捕获到的,但是通过eXosip_event_wait没有收到数据,这是一个异步的处理方案,最终发现是开启防火墙导致的问题


事件接收逻辑

eXosip_listen_addr绑定端口,监听数据

osip_thread_create 创建线程,采用select方式等待数据

int

_eXosip_read_message (struct eXosip_t *excontext, int max_message_nb, int sec_max, int usec_max)

该函数调用select函数,等待接收SIP报文发送过来,超时继续等待

当接收到数据到达的信号,调用excontext->eXtl_transport.tl_read_message (excontext, &osip_fdset, &osip_wrset);开始接收,

tl_read_message是一个函数指针,根据不同的协议类型,选择最终的具体调用,例如UDP的话,实现函数是udp_tl_read_message

调用_eXosip_handle_incoming_message去解析SIP报文,放进队列里面

用户层调用eXosip_event_wait获取事件进行处理


UDP SIP报文接收

代码

static int

udp_tl_read_message (struct eXosip_t *excontext, fd_set * osip_fdset, fd_set * osip_wrset)

当底层select接收到一个事件,调用该函数,通过recvfrom函数接收SIP报文

问题

else if (i < 0) {
#ifdef _WIN32_WCE
      int my_errno = 0;
#else
      int my_errno = errno;
#endif
      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not read socket (%i) (%i) (%s)\n", i, my_errno, strerror (my_errno)));
      if (errno == 0 || errno == 34) {
         udp_message_max_length = udp_message_max_length * 2;
         osip_free (reserved->buf);
         reserved->buf = (char *) osip_malloc (udp_message_max_length * sizeof (char) + 1);
      }
      if (my_errno == 57) {
        _udp_tl_reset_oc (excontext, reserved->udp_socket_oc_family);
      }

一旦接收到目标主机不可达的数据包,就会触发该语句,errno为0, 并且udp_message_max_length会翻倍,因此多次出现目标主机不可达,就会导致申请内存失败,从而再也无法接收处理数据

if (reserved->buf == NULL)
      reserved->buf = (char *) osip_malloc (udp_message_max_length * sizeof (char) + 1);
    if (reserved->buf == NULL)
      return OSIP_NOMEM;

因此申请内存这个操作必须注释掉,有两处代码,实际上SIP报文不会超过8000最大的,因此没有必要翻倍


UDP接收套接字的接收或者发送缓存的设置

函数处理接收的SIP报文

static int

udp_tl_open (struct eXosip_t *excontext)

在这里加大接收和发送缓存


 unsigned int sendbuf= 1024 * 1024 * 20, recvbuf=1024*1024*20;

setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&sendbuf, sizeof(sendbuf));

setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&recvbuf, sizeof(sendbuf));