SCTP 庫的簡述和代碼 (5)

用戶接口設計app

設計需求:socket

接口API, RFC4960有規範, 基本上按照設計就能夠了. 須要考慮的地方時, 1. 提供簡化的接口,方便懶人. 2. 因爲設計此SCTP庫的目的是用於p2p傳輸, 因此,要考慮方便服務於p2p的庫.ide

 

定義了一個以下回調函數表,  當有鏈接請求或數據到達時, 回調.函數

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;ui

sctp_pkg_snd 是可選的參數, 若是你想對數據的發送方法作特殊處理, 能夠覆蓋庫的缺省動做. 若是不設置此函數,那麼, 將直接發送到對方IP地址:接收SCTP包的UDP端口.debug

data_received_cb, 有SCTP包到達時被觸發.設計

retrieve_cb, sctp一個流斷掉後, 沒有確認的數據包能夠用此函數提取, 保證高可靠性.接口

 

接口API:ip

入參, 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; }

相關文章
相關標籤/搜索