SCTP 库的简述和代码 (5)

用户接口设计

设计需求:

接口API, RFC4960有规范, 基本上按照设计就可以了. 需要考虑的地方时, 1. 提供简化的接口,方便懒人. 2. 由于设计此SCTP库的目的是用于p2p传输, 所以,要考虑方便服务于p2p的库.

 

定义了一个如下回调函数表,  当有连接请求或数据到达时, 回调.

typedef struct sctp_call_back_ {
    sctp_pkg_snd_fn sctp_pkg_snd;
    data_received_fn data_received_cb;
    sctp_assoc_up_fn   assoc_up_cb;
    sctp_assoc_down_fn assoc_down_cb;
    sctp_retrieve_fn retrieve_cb;
    sctp_debug_fn debug_cb;
}sctp_call_back;

sctp_pkg_snd 是可选的参数, 如果你想对数据的发送方法做特殊处理, 可以覆盖库的缺省动作. 如果不设置此函数,那么, 将直接发送到对方IP地址:接收SCTP包的UDP端口.

data_received_cb, 有SCTP包到达时被触发.

retrieve_cb, sctp一个流断掉后, 没有确认的数据包可以用此函数提取, 保证高可靠性.

 

接口API:

入参, udp_port, 用于sctp流的udp端口. ctx, 可选, 用户提供的上下文, 对sctp库来说,透明,方便上层应用.

返回成功/失败

BOOL sctp_init(sctp_call_back* sctp_cb, uint16 udp_port, void *ctx)

返回 instance, 起一个sctp的服务socket, 相当于listen
int sctp_listen(uint16 local_port, uint32 local_ip);

 

返回assoc id, 相当与connect

peer_id是可选项, 16字节.  用来和p2p库一起使用时, 此peer_id包含了对方的IP地址,端口等. 对方可以是一个有公共网IP的节点,此时, 根据peer_id可以得到对方地址直接使用. 当对方在一个私网中,此id可用来请p2p库帮忙路由数据包到达对方. 简单的说, 在p2p网中, 重要的是peer_id,有了它就可以找到对方, 此peer_id起到的作用就是IP地址的作用.

int sctp_connect(int instance, uint32 peer_ip,  uint16 dst_port, uchar *peer_id);

 

相当于send

int sctp_send_data(int assoc_id, uchar *buf, uint16 len)

例子:

初始化:

入口参数是用来传输sctp数据的udp端口号. 如果是在局域网中,这个端口可能和NAT后的端口不一样,简单的说,就是本机服务端口:
int app_sctp_init(uint16 sctp_udp_port)
{
 sctp_call_back call_cb;

 memset(&call_cb, 0, sizeof(call_cb));
 call_cb.assoc_down_cb = assoc_down;
 call_cb.assoc_up_cb = assoc_up;
 call_cb.data_received_cb = data_rcvd;
 call_cb.sctp_pkg_snd = send_sctp_pkg;
 sctp_init(&call_cb, VIDEO_UDP_PORT, p2p_hdl);
 return TRUE;
}

 

回调函数:
int assoc_down(int assoc_id, int reason)
{
 if (vedioDlg->videoAssoc == assoc_id)
 {
  vedioDlg->videoAssoc = 0;
  vedioDlg->ShowWindow(SW_HIDE);
  memset(guiDlg->active_video_peer, 0, 16);
 }
 return 0;
}

int assoc_up(int instance, int assoc_id, unsigned short peer_port, int in_stream, int out_stream)

 vedioDlg->videoAssoc = assoc_id;
 vedioDlg->ShowWindow(SW_SHOW);
 return 0;
}

int data_rcvd(int assoc_id, unsigned char *buf, unsigned short len,
 unsigned short stream_id, int protocol, int part_data)
{
 if (vedioDlg->isCaptureStarted == FALSE)
 {
  // user has not click start video yet
  sctp_consume_data(assoc_id, buf, len);
  return len;
 } 
 PostMessage(guiDlg->m_hWnd, WM_VIDEODATA, (WPARAM)buf, (LPARAM)len);
 return len;
}

 

你可能感兴趣的:(SCTP 库的简述和代码 (5))