SIP servlet,chatserver

我正在尝试让SIP servlet聊天服务器与此处的textclient一起工作。

当我使用2个客户端向对方发送消息(点对点)时,一切顺利。 但是当我将一个或多个客户端与我的服务器一起使用时,我必须等待32秒,然后服务器才会在doMessage()方法中获取任何新消息。 我正在使用Netbeans和Sailfin作为我的SIP服务器。 我正在调查Sailfin中的请求或响应之间是否存在某种限制或可配置的延迟或超时?

如果需要,我可以发布服务器代码。

谢谢

这是服务器的代码,我将尝试稍后进行wireshark跟踪。

 public class ChatroomSipServlet extends SipServlet { public final static String USER_LIST = "userList"; public final static String CHATROOM_SERVER_NAME = "chatroomservername"; public String serverAddress; public SipFactory factory; @Override public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); System.out.println("Chatroom sip servlet is gestart!"); try { factory = (SipFactory) getServletContext().getAttribute("javax.servlet.sip.SipFactory"); System.out.println("Sip Factory: " + factory); } catch (Exception e) { throw new ServletException("Factory probleem!", e); } getServletContext().setAttribute(USER_LIST, new ArrayList()); serverAddress = getServletConfig().getInitParameter(CHATROOM_SERVER_NAME); System.out.println("serverAddress is: " + serverAddress); } @Override public void destroy() { try { sendToAll(serverAddress, "Server sluit af!"); } catch (Throwable e) { e.printStackTrace(); } super.destroy(); } protected void doMessage(SipServletRequest request) throws ServletException, IOException { System.out.println(getDateTime() + " Bericht ontvangen"); request.createResponse(SipServletResponse.SC_OK).send(); String message = request.getContent().toString(); String from = ((SipURI) request.getFrom().getURI()).toString(); if (message.equalsIgnoreCase("/quit")) { sendToUser(from, "Bye"); removeUser(from); return; } if (!containsUser(from)) { sendToUser(from, "Welkom in de chatroom. Typ '/quit' om af te sluiten."); addUser(from); } if (message.equalsIgnoreCase("/who")) { String users = "Lijst van de gebruikers:\n"; List list = (List) getServletContext().getAttribute(USER_LIST); for (String user : list) { users += user + "\n"; } sendToUser(from, users); return; } if (message.equalsIgnoreCase("/join")) { return; } sendToAll(from, message); } protected void doErrorResponse(SipServletResponse response) throws ServletException, IOException { // String receiver = response.getTo().toString(); String receiver = ((SipURI) response.getTo().getURI()).toString(); System.out.println(getDateTime() + " Errorresponse voor " + receiver); removeUser(receiver); } protected void doSuccessResponse(SipServletResponse response) throws ServletException, IOException { response.getApplicationSession().invalidate(); } private void sendToAll(String from, String message) throws ServletParseException, IOException { List list = (List) getServletContext().getAttribute(USER_LIST); for (String user : list) { SipApplicationSession session = factory.createApplicationSession(); System.out.println(getDateTime() + " Session created voor " + user); SipServletRequest request = factory.createRequest(session, "MESSAGE", serverAddress, user); String msg = from + " stuurt: \n" + message; request.setContent(msg.getBytes(), "text/plain"); request.send(); } } private void sendToUser(String to, String message) throws ServletParseException, IOException { SipApplicationSession session = factory.createApplicationSession(); SipServletRequest request = factory.createRequest(session, "MESSAGE", serverAddress, to); request.setContent(message.getBytes(), "text/plain"); request.send(); } private boolean containsUser(String from) { List list = (List) getServletContext().getAttribute(USER_LIST); return list.contains(from); } private void addUser(String from) { List list = (List) getServletContext().getAttribute(USER_LIST); list.add(from); } private void removeUser(String from) { System.out.println(getDateTime() + " " + from + " wordt verwijderd uit de lijst."); List list = (List) getServletContext().getAttribute(USER_LIST); list.remove(from); } @Override protected void doRegister(SipServletRequest req) throws ServletException, IOException { System.out.println("Register request ontvangen: " + req.getTo()); int response = SipServletResponse.SC_OK; SipServletResponse resp = req.createResponse(response); resp.send(); } private String getDateTime() { DateFormat dateFormat = new SimpleDateFormat("[" + "HH:mm:ss" + "]"); Date date = new Date(); return dateFormat.format(date); } } 

和sip.xml

  sip.chatvoorbeeld.ChatServer Chatroom Sip Servlet Chatroom Sip Servlet   ChatroomSipServlet    5   ChatroomSipServlet ChatroomSipServlet Chatroom SIP servlet  sip.chatvoorbeeld.ChatroomSipServlet   chatroomservername sip:chatserver@192.168.56.1:5060  1   

我还尝试了一个空的servlet,只是使用doMessage()方法打印出“收到的消息”。 同样的32秒延迟……

Wireshark给了我:

我将消息“test”发送到服务器:

 MESSAGE sip:chatserver@192.168.56.1:5060;transport=udp SIP/2.0 Call-ID: aba00c2646a9b4e6df3b15df19dbf58d@192.168.56.101 CSeq: 1 MESSAGE From: "bobby" ;tag=textclientv1.0 To: "chatserver"  Via: SIP/2.0/UDP 192.168.56.101:5095;branch=branch1 Max-Forwards: 70 Contact: "bobby"  Content-Type: text/plain Content-Length: 4 test 

服务器发回:

 SIP/2.0 200 OK Content-Length: 0 To: "chatserver";tag=g9vdns7u-e Cseq: 1 MESSAGE Via: SIP/2.0/UDP 192.168.56.101:5095;branch=branch1 From: "bobby";tag=textclientv1.0 Call-Id: aba00c2646a9b4e6df3b15df19dbf58d@192.168.56.101 Server: Glassfish_SIP_2.0.0 MESSAGE sip:bobby@192.168.56.101:5095 SIP/2.0 Max-Forwards: 69 Content-Length: 43 To:  Cseq: 1 MESSAGE Via: SIP/2.0/UDP 192.168.56.1:5060;branch=z9hG4bKdaacb7673c871796474ca951221a6643db6c Content-Type: text/plain Call-Id: 192.168.56.1_11_6595680936174578736 From: ;tag=g9vdns7u-g sip:bobby@192.168.56.101:5095 stuurt: test 

然后我的客户再次回答OK:

 SIP/2.0 200 OK To: ;tag=888 CSeq: 1 MESSAGE Via: SIP/2.0/UDP 192.168.56.1:5060;branch=z9hG4bKdaacb7673c871796474ca951221a6643db6c;received=192.168.56.1 Call-ID: 192.168.56.1_11_6595680936174578736 From: ;tag=g9vdns7u-g Content-Length: 0 

到目前为止一切顺利,一切顺利。 但现在我发送第二条消息到服务器“test2”,我得到了这个:

客户端到服务器:

 MESSAGE sip:chatserver@192.168.56.1:5060;transport=udp SIP/2.0 Call-ID: 95ad65365378b9b6b5bd7ad3629f7b02@192.168.56.101 CSeq: 1 MESSAGE From: "bobby" ;tag=textclientv1.0 To: "chatserver"  Via: SIP/2.0/UDP 192.168.56.101:5095;branch=branch1 Max-Forwards: 70 Contact: "bobby"  Content-Type: text/plain Content-Length: 5 test2 

然后服务器确实响应:

 SIP/2.0 200 OK Content-Length: 0 To: "chatserver";tag=g9vdns7u-e Cseq: 1 MESSAGE Via: SIP/2.0/UDP 192.168.56.101:5095;branch=branch1 From: "bobby";tag=textclientv1.0 Call-Id: aba00c2646a9b4e6df3b15df19dbf58d@192.168.56.101 Server: Glassfish_SIP_2.0.0 

然后通信停止…我得到200 OK,但我的doMessage()方法中的println()没有传递。

32秒是事务的正常超时(在RFC3261中表示为64 * T1,其中T1的默认值为500毫秒。)

我没有直接想法解决您的问题,除了超时很可能不是SailFin中的错误配置。 所以请提供wireshark跟踪和服务器代码!

要回答我自己的问题,如果有人遇到同样的问题,我发现这是textclient中的一个错误,违反了RFC 3261的8.1.1.7节。

对于UA发送的所有请求,分支参数值必须在空间和时间上是唯一的。 此规则的例外情况是CANCEL和非2xx响应的ACK。 如下所述,CANCEL请求将具有与其取消的请求相同的分支参数值。 如第17.1.1.3节所述,非2xx响应的ACK也将具有与其确认响应的INVITE相同的分支ID。

分支ID参数的唯一性属性,以便于将其用作事务ID,不属于RFC 2543。

符合此规范的元素插入的分支ID必须始终以字符“z9hG4bK”开头。

SipLayer.java中的以下行

 ViaHeader viaHeader = headerFactory.createViaHeader(getHost(), getPort(), "udp", "branch1"); 

将使用“branch1”参数创建每条消息。 使此参数唯一可以解决问题。