2012-02-13 127 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)&看到您发送的包&接收。然后查看套接字问题。