用戶接口設計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; }