2012-02-13 128 views
0

我目前正在研究SIP示例應用程序。SIP註冊問題

我想在Unix上使用基於C的Socket編程進行註冊。我已經成功地獲得了PJSIP的註冊,但是當我使用正常的套接字編程發送相同的參數時,我無法從服務器收到任何響應。

這裏是源代碼:

char *server = (char *)serverAddress; // First arg: server address/name 
char *echoString = "Request msg REGISTER/cseq=46476 (tdta0x8857200)\r\nREGISTER sip:DOMAIN_NAME SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.1.120:51648;rport;branch=z9hG4bKPjwEt4VvIVdjIJKRmEJbkidYDAu-zQbIqv\r\nMax-Forwards: 70\r\nFrom: <sip:[email protected]_NAME>;tag=epCBN7JXsQE1nnI5d5SOZe9a5ujRyI67\r\nTo: <sip:[email protected]_NAME>\r\nCall-ID: .5yYCqh2jEYdy5T4kxhzxwDYEkCO1XlD\r\nCSeq: 46476 REGISTER\r\nContact: <sip:[email protected]:51648;ob>\r\nExpires: 300\r\nAllow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS\r\nAuthorization: Digest username=\"USER_NAME\", realm=\"asterisk\", nonce=\"3b63254c\", uri=\"sip:DOMAIN_NAME\", response=\"9e8fc78829d143a58fba5a79f6ad44fd\", algorithm=MD5\r\nContent-Length: 0"; 


size_t echoStringLen = strlen(echoString); 


// Third arg (optional): server port/service 
char *servPort = (char *)service; 

// Tell the system what kind(s) of address info we want 
struct addrinfo addrCriteria;      // Criteria for address match 
memset(&addrCriteria, 0, sizeof(addrCriteria)); // Zero out structure 
addrCriteria.ai_family = AF_UNSPEC;    // For the following fields, a zero value means 
                // Any address family "don't care" 


addrCriteria.ai_socktype = SOCK_DGRAM; // Only datagram sockets 
addrCriteria.ai_protocol = IPPROTO_UDP;   // Only UDP protocol 
// Get address(es) 
struct addrinfo *servAddr; // List of server addresses 
int rtnVal = getaddrinfo(server, servPort, &addrCriteria, &servAddr); 
if (rtnVal != 0) 
    DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal)); 
// Create a datagram/UDP socket 
int sock = socket(servAddr->ai_family, servAddr->ai_socktype, 
        servAddr->ai_protocol); // Socket descriptor for client 
if (sock < 0) 
    DieWithSystemMessage("socket() failed"); 
// Send the string to the server 
ssize_t numBytes = sendto(sock, echoString, echoStringLen, 0, 
          servAddr->ai_addr, servAddr->ai_addrlen); 
if (numBytes < 0) 
    DieWithSystemMessage("sendto() failed"); 
else if (numBytes != echoStringLen) 
    DieWithUserMessage("sendto() error", "sent unexpected number of bytes"); 
// Receive a response 
struct sockaddr_storage fromAddr; // Source address of server 
// Set length of from address structure (in-out parameter) 
socklen_t fromAddrLen = sizeof(fromAddr); 
char buffer[100 + 1]; // I/O buffer 
numBytes = recvfrom(sock, buffer, 100, 0, 
        (struct sockaddr *) &fromAddr, &fromAddrLen); 
if (numBytes < 0) 
    DieWithSystemMessage("recvfrom() failed"); 
else if (numBytes != 100) 
    DieWithUserMessage("recvfrom() error", "received unexpected number of bytes"); 
// Verify reception from expected source 

int value = SockAddrsEqual(servAddr->ai_addr, (struct sockaddr *) &fromAddr); 
if (value == 0) 
    DieWithUserMessage("recvfrom()", "received a packet from unknown source"); 
freeaddrinfo(servAddr); 
buffer[echoStringLen] = '\0';  // Null-terminate received data 
printf("Received: %s\n", buffer); // Print the echoed string 

close(sock); 
exit(0); 

當我試圖調試代碼,然後斷點會從recvfrom的方法調用消失如下。

numBytes = recvfrom(sock, buffer, 100, 0, (struct sockaddr *) &fromAddr, &fromAddrLen); 

在此先感謝您的合作。

+0

「斷點消失」是什麼意思?你的程序崩潰了嗎?至於事情的SIP方面,您正在使用的方法將無法正常工作,因爲您試圖重播現有的REGISTER請求。服務器會因多種原因拒絕重播請求,包括重複的SIP事務和使用陳舊的隨機數。 – sipwiz 2012-02-13 11:51:42

+0

該應用程序既不崩潰也不前進。看來,該應用程序正在等待服務器響應recv方法。但使用其他軟電話,我已經能夠註冊很多次了。由於SIP註冊在一定的時間間隔內有效,並且在此之後它正在取消註冊。爲了維護會話,我們需要重新註冊SIP服務器。 – 2012-02-13 12:01:36

回答

0

如果您沒有得到註冊服務器服務器的響應,很可能是因爲它無法理解您發送的REGISTER請求或拒絕它作爲副本。更可能的是,您需要更深入地瞭解如何構建REGISTER請求,而不是簡單地發送硬編碼的字符串。

除此之外,你可以嘗試的是在你的echoString的末尾添加所需的\ r \ n \ r \ n。所有SIP請求都需要以雙行換行符結束標題部分,並且字符串中缺少該部分。

0

recvfrom()阻塞直到收到響應,除非您將套接字設置爲非阻塞。一個更好的方法是使用select()超時(如一秒或兩秒)。更好的辦法是把整個事情放到一個循環中重試一些次數(比如三次或四次)。

請記住,UDP不保證您的數據報將被傳送:完全取決於您自己決定何時等待足夠長時間並需要重試。

另外,檢查servAddrgetaddrinfo()的值是否有意義。如果地址或端口號錯誤,您的數據包可能會悄然消失。

0

如果您確認這是套接字問題,那麼很好追蹤。

但是,如果您不確定那麼對於這種問題使用網絡分析應用程序(wireshark)&看到您發送的包&接收。然後查看套接字問題。