我最近正在基於usrsctp的項目工作。usrsctp數據收到回調參數值變成廢話
當創建一個新的SCTP套接字時,可以指定一個回調函數,當新數據可用時將會調用該函數,如下面的代碼所示。
創建一個新的SCTP套接字:
struct socket *s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP,
sctp_data_received_cb, NULL, 0, sctp);
回調函數:
static int
sctp_data_received_cb(struct socket *sock, union sctp_sockstore addr, void *data,
size_t len, struct sctp_rcvinfo recv_info, int flags, void *user_data)
{
struct sctp_transport *sctp = (struct sctp_transport *)user_data;
if (sctp == NULL || len == 0)
return -1;
fprintf(stdout, "Data of length %u received on stream %u with SSN %u, TSN %u, PPID %u\n",
(uint32_t)len,
recv_info.rcv_sid,
recv_info.rcv_ssn,
recv_info.rcv_tsn,
ntohl(recv_info.rcv_ppid));
if (flags & MSG_NOTIFICATION)
handle_notification_message(sctp, (union sctp_notification *)data, len);
else
handle_rtcdc_message(sctp, data, len, ntohl(recv_info.rcv_ppid), recv_info.rcv_sid);
free(data);
return 0;
}
這個回調函數將被正常調用,但是它的參數值都只是無稽之談。上面的代碼的輸出是等
Data of length 675381504 received on stream 31504 with SSN 34835, TSN 32651, PPID 8470824
應該一直喜歡
Data of length 18 received on stream 0 with SSN 0, TSN 4117987333, PPID 50
我讀usrsctp的源代碼,並發現其中的回調被調用:
if (control->spec_flags & M_NOTIFICATION) {
flags |= MSG_NOTIFICATION;
}
inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info);
SCTP_TCB_LOCK(stcb);
將其更改爲以下代碼並重新編譯庫
if (control->spec_flags & M_NOTIFICATION) {
flags |= MSG_NOTIFICATION;
}
fprintf(stdout, "[LIB] Data of length %u received on stream %u with SSN %u, TSN %u, PPID %u\n",
control->length,
rcv.rcv_sid,
rcv.rcv_ssn,
rcv.rcv_tsn,
ntohl(rcv.rcv_ppid));
inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info);
SCTP_TCB_LOCK(stcb);
我能得到預期的輸出:
[LIB] Data of length 18 received on stream 0 with SSN 0, TSN 4117987333, PPID 50
爲什麼參數值成爲回調函數廢話?
我發現了一個類似的問題here,但無法理解它的答案。我很肯定這是同一個問題。
[UPDATE1]
usrsctp_socket的usrsctp.h原型:
struct socket *
usrsctp_socket(int domain, int type, int protocol,
int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info),
int (*send_cb)(struct socket *sock, uint32_t sb_free),
uint32_t sb_threshold,
void *ulp_info);
[UPDATE2]
我敢肯定,需要在the old similar thread提示沒有額外的技巧,因爲我在official examples中看到沒有奇怪的鑄件,他們只是運作良好。
例如echo_server.c:
static int
receive_cb(struct socket *sock, union sctp_sockstore addr, void *data,
size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info)
{
char namebuf[INET6_ADDRSTRLEN];
const char *name;
uint16_t port;
if (data) {
if (flags & MSG_NOTIFICATION) {
printf("Notification of length %d received.\n", (int)datalen);
} else {
switch (addr.sa.sa_family) {
#ifdef INET
case AF_INET:
name = inet_ntop(AF_INET, &addr.sin.sin_addr, namebuf, INET_ADDRSTRLEN);
port = ntohs(addr.sin.sin_port);
break;
#endif
#ifdef INET6
case AF_INET6:
name = inet_ntop(AF_INET6, &addr.sin6.sin6_addr, namebuf, INET6_ADDRSTRLEN),
port = ntohs(addr.sin6.sin6_port);
break;
#endif
case AF_CONN:
#ifdef _WIN32
_snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr);
#else
snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr);
#endif
name = namebuf;
port = ntohs(addr.sconn.sconn_port);
break;
default:
name = NULL;
port = 0;
break;
}
printf("Msg of length %d received from %s:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u.\n",
(int)datalen,
name,
port,
rcv.rcv_sid,
rcv.rcv_ssn,
rcv.rcv_tsn,
ntohl(rcv.rcv_ppid),
rcv.rcv_context);
if (flags & MSG_EOR) {
struct sctp_sndinfo snd_info;
snd_info.snd_sid = rcv.rcv_sid;
snd_info.snd_flags = 0;
if (rcv.rcv_flags & SCTP_UNORDERED) {
snd_info.snd_flags |= SCTP_UNORDERED;
}
snd_info.snd_ppid = rcv.rcv_ppid;
snd_info.snd_context = 0;
snd_info.snd_assoc_id = rcv.rcv_assoc_id;
if (usrsctp_sendv(sock, data, datalen, NULL, 0, &snd_info, sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) {
perror("sctp_sendv");
}
}
}
free(data);
}
return (1);
}
我不這麼認爲,我已經將usrsctp_socket的原型添加到了問題中。 – xhs 2015-02-11 13:17:05
這是合理的,我會嘗試。但在官方的[例子](https://sctp-refimpl.googlecode.com/svn/trunk/KERN/usrsctp/programs/)中,我沒有看到這些鑄造的東西,他們只是工作得很好。 – xhs 2015-02-11 13:37:03
嗨,@ joachim-pileborg,我再次更新了我的問題。我仍然堅持認爲它與'addr'參數無關。 – xhs 2015-02-11 14:11:11