private void doMaxMessageSize(String path, long size, boolean expectOpen) throws Exception { Tomcat tomcat = getTomcatInstance(); // Must have a real docBase - just use temp Context ctx = tomcat.addContext("", System.getProperty("java.io.tmpdir")); ctx.addApplicationListener( new ApplicationListener(TesterEchoServer.Config.class.getName(), false)); Tomcat.addServlet(ctx, "default", new DefaultServlet()); ctx.addServletMapping("/", "default"); tomcat.start(); WebSocketContainer wsContainer = ContainerProvider.getWebSocketContainer(); Session s = connectToEchoServer(wsContainer, EndpointA.class, path); StringBuilder msg = new StringBuilder(); for (long i = 0; i < size; i++) { msg.append('x'); } s.getBasicRemote().sendText(msg.toString()); // Wait for up to 5 seconds for session to close boolean open = s.isOpen(); int count = 0; while (open != expectOpen && count < 50) { Thread.sleep(100); count++; open = s.isOpen(); } Assert.assertEquals(Boolean.valueOf(expectOpen), Boolean.valueOf(s.isOpen())); }
@Test public void testSessionExpiryContainer() throws Exception { Tomcat tomcat = getTomcatInstance(); // Must have a real docBase - just use temp Context ctx = tomcat.addContext("", System.getProperty("java.io.tmpdir")); ctx.addApplicationListener( new ApplicationListener(TesterEchoServer.Config.class.getName(), false)); Tomcat.addServlet(ctx, "default", new DefaultServlet()); ctx.addServletMapping("/", "default"); tomcat.start(); // Need access to implementation methods for configuring unit tests WsWebSocketContainer wsContainer = (WsWebSocketContainer) ContainerProvider.getWebSocketContainer(); // 5 second timeout wsContainer.setDefaultMaxSessionIdleTimeout(5000); wsContainer.setProcessPeriod(1); connectToEchoServer(wsContainer, EndpointA.class, TesterEchoServer.Config.PATH_BASIC); connectToEchoServer(wsContainer, EndpointA.class, TesterEchoServer.Config.PATH_BASIC); Session s3a = connectToEchoServer(wsContainer, EndpointA.class, TesterEchoServer.Config.PATH_BASIC); // Check all three sessions are open Set<Session> setA = s3a.getOpenSessions(); Assert.assertEquals(3, setA.size()); int count = 0; boolean isOpen = true; while (isOpen && count < 8) { count++; Thread.sleep(1000); isOpen = false; for (Session session : setA) { if (session.isOpen()) { isOpen = true; break; } } } if (isOpen) { for (Session session : setA) { if (session.isOpen()) { System.err.println("Session with ID [" + session.getId() + "] is open"); } } Assert.fail("There were open sessions"); } }
private int getOpenCount(Set<Session> sessions) { int result = 0; for (Session session : sessions) { if (session.isOpen()) { result++; } } return result; }
public static void encodeCommonReply( Session session, String token, String username, String text) { if (session.isOpen()) { try { session.getBasicRemote().sendText(token + DELIMITER + username + DELIMITER + text); } catch (IOException e) { e.printStackTrace(); } } }
private void activeClose(CloseReason reason) { try { if (thisSession.isOpen()) { LOG.debug("Closing connection to peer: " + thisSession.getId()); thisSession.close(reason); } } catch (IOException e) { LOG.error(e); } }
protected void disconnect(String reason) { Session wsSession = _wsSession; _wsSession = null; if (wsSession != null && wsSession.isOpen()) { logger.debug("Closing websocket session {}", wsSession); try { wsSession.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, reason)); } catch (IOException x) { logger.trace("Could not close websocket session " + wsSession, x); } } }
/** * Notifies the specified timeline message to browsers. * * @param message the specified message, for example * <pre> * { * "type": "article", * "content": "" * } * </pre> */ public static void notifyTimeline(final JSONObject message) { final String msgStr = message.toString(); final Iterator<Session> i = SESSIONS.iterator(); while (i.hasNext()) { final Session session = i.next(); if (session.isOpen()) { session.getAsyncRemote().sendText(msgStr); } } }
public synchronized void putNewSession(String sid, Session session) { Session other = this.savedSessionMap.get(sid); if (other != null && other.isOpen()) { try { other.close(); } catch (IOException ex) { this.logger.error("websocket-close sid:{} error:{}", sid, ex.getMessage()); } } this.savedSessionMap.put(sid, session); this.logger.debug("websocket-session add new sid:{}", sid); }
@OnMessage public void onMessage(final Session session, final String chatMessage) { String room = (String) session.getUserProperties().get("room"); try { for (Session s : session.getOpenSessions()) { if (s.isOpen()) { s.getBasicRemote().sendText(chatMessage); } } } catch (IOException e) { log.log(Level.WARNING, "onMessage failed", e); } }
/** * Message received. * * @param message message * @param session session */ @OnMessage public void onMessage(String message, Session session) { System.out.println("\nOnMessage: " + message); for (Session sess : session.getOpenSessions()) { if (sess != session && sess.isOpen()) try { sess.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } }
private void sendMessage(final Message serverMsg) { final Gson gson = new Gson(); try { final String jsonStr = gson.toJson(serverMsg); if (thisSession.isOpen()) { LOG.debug("Send: " + jsonStr + " to: " + thisSession.getId()); thisSession.getBasicRemote().sendText(jsonStr); } } catch (Exception e) { LOG.error(e); } }
@Override public boolean asyncPush(String sid, String message) { boolean result = false; Session session = this.savedSessionMap.get(sid); if (session != null && session.isOpen()) { result = true; session.getAsyncRemote().sendText(message); this.logger.debug("websocket-push message:{},{}", sid, message); } else { this.logger.debug("websocket-push message:sid:{} not exist or closed", sid); } return result; }
public synchronized void sendMessage(final String message) { /* * if Packet is bigger than 1000 Send the message through of sendDividedChain */ if (message.length() > 1000) { try { sendDividedChain(message); } catch (Exception e) { e.printStackTrace(); } } else { if (clientConnection != null && clientConnection.isOpen()) clientConnection.getAsyncRemote().sendText(message); } }
/** * deprecated: 发送数据方法,根据session的hashcode找对应sess客户端 * * <p>并发送数据,发送完return * * <p>date 2015-03-08 * * @author sharkTang * @param session * @param closeReason */ private void sendData() { if (null != webSessionMap && webSessionMap.size() > 0) { Session sess = webSessionMap.get(webSocketHashCodeStatic); // System.out.println(sess.getQueryString()); try { if (null != sess && sess.isOpen()) { // sessionsStatic = // PuFaBigPingWebSocketServer.daPingWebsocketSession; sess.getAsyncRemote().sendText(sendDataStatic); // if (sendDataStatic.length() <= 0) { // sendDataStatic = WebSocketConstants.SPACESTR_ENG; // // } } } catch (Exception ex) { logger_.info(sess.hashCode() + " 客户端发送数据异常,异常信息:" + ex.getMessage()); } } }
@OnError public void errorHandle(Session session, Throwable error) { if (session != null && session.isOpen()) { WebsocketMessageWrapper<Error> response = new WebsocketMessageWrapper<>(); response.setType(WebsocketMessageType.CUSTOMER_ERROR); response.setData(new Error()); if (error instanceof CustomerNotFoundException) { response.setSequenceId(((CustomerNotFoundException) error).getSequenceId()); response.getData().setCode("customer.notFound"); response.getData().setDescription("Customer not found"); } else { WebSocketServerLogger.LOG.handleWebsocketServerError(error); response.setSequenceId(UUID.randomUUID().toString()); response.getData().setCode(error.getClass().getName()); response.getData().setDescription("Handled exception"); } session.getAsyncRemote().sendObject(response); } }
/** * 上线 广播消息 * * @param object { nickname } * @param sessionID * @return private final static String rs = "var rs = * {type:'${0}',nickname:'${1}',mucname:'${2}',msg:'${3}'}"; */ public String broadcast(JSONObject object, String sessionID) { // Session session = sess_map.get(sessionID); // session.getBasicRemote().sendText(""); String nickname = (String) object.get("nickname"); Collection<Session> values = sess_map.values(); Iterator<Session> iterator = values.iterator(); // {type:'broadcast',nick:''} String rs1 = rs.replace("${type}", "online") .replace("${nickname}", nickname) .replace("${sessionID}", sessionID); while (iterator.hasNext()) { try { Session sess = iterator.next(); if (sess.isOpen() && !sess.getId().equals(sessionID)) { // 排除当前客户端 sess.getBasicRemote().sendText(rs1); } } catch (IOException e) { e.printStackTrace(); } } return null; }
private void doBufferTest( boolean isTextBuffer, boolean isServerBuffer, boolean isTextMessage, boolean pass) throws Exception { Tomcat tomcat = getTomcatInstance(); // Must have a real docBase - just use temp Context ctx = tomcat.addContext("", System.getProperty("java.io.tmpdir")); ctx.addApplicationListener( new ApplicationListener(TesterEchoServer.Config.class.getName(), false)); Tomcat.addServlet(ctx, "default", new DefaultServlet()); ctx.addServletMapping("/", "default"); WebSocketContainer wsContainer = ContainerProvider.getWebSocketContainer(); if (isServerBuffer) { if (isTextBuffer) { ctx.addParameter( org.apache.tomcat.websocket.server.Constants .TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM, "1024"); } else { ctx.addParameter( org.apache.tomcat.websocket.server.Constants .BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM, "1024"); } } else { if (isTextBuffer) { wsContainer.setDefaultMaxTextMessageBufferSize(1024); } else { wsContainer.setDefaultMaxBinaryMessageBufferSize(1024); } } tomcat.start(); Session wsSession = wsContainer.connectToServer( TesterProgrammaticEndpoint.class, ClientEndpointConfig.Builder.create().build(), new URI("ws://localhost:" + getPort() + TesterEchoServer.Config.PATH_BASIC)); BasicHandler<?> handler; CountDownLatch latch = new CountDownLatch(1); TesterEndpoint tep = (TesterEndpoint) wsSession.getUserProperties().get("endpoint"); tep.setLatch(latch); if (isTextMessage) { handler = new BasicText(latch); } else { handler = new BasicBinary(latch); } wsSession.addMessageHandler(handler); if (isTextMessage) { wsSession.getBasicRemote().sendText(MESSAGE_TEXT_4K); } else { wsSession.getBasicRemote().sendBinary(ByteBuffer.wrap(MESSAGE_BINARY_4K)); } boolean latchResult = handler.getLatch().await(10, TimeUnit.SECONDS); Assert.assertTrue(latchResult); Queue<?> messages = handler.getMessages(); if (pass) { Assert.assertEquals(1, messages.size()); if (isTextMessage) { Assert.assertEquals(MESSAGE_TEXT_4K, messages.peek()); } else { Assert.assertEquals(ByteBuffer.wrap(MESSAGE_BINARY_4K), messages.peek()); } } else { // When the message exceeds the buffer size, the WebSocket is // closed. The endpoint ensures that the latch is cleared when the // WebSocket closes. However, the session isn't marked as closed // until after the onClose() method completes so there is a small // window where this test could fail. Therefore, wait briefly to // give the session a chance to complete the close process. for (int i = 0; i < 500; i++) { if (!wsSession.isOpen()) { break; } Thread.sleep(10); } Assert.assertFalse(wsSession.isOpen()); } }
@Override public void run() { final Semaphore sem = new Semaphore(0); final List<String> logs = new ArrayList<String>(); final Map<String, List<String>> logsToSync = new HashMap<String, List<String>>(); final List<Session> sessions = new ArrayList<Session>(); GenericWebsocketClient gwc = new GenericWebsocketClient( new WebsocketClient() { @Override public void onOpen(final Session session, EndpointConfig config) { try { sessions.add(session); String sid = session.getId(); List<String> sl = Collections.synchronizedList(new ArrayList<String>(logs)); logsToSync.put(sid, sl); for (String id : sl) { AttLog log = attLogsManager.findById(id); String json = attLogSerializer.toJson(log); String cmdJson = "attLog;" + json; logger.info(cmdJson); session.getBasicRemote().sendText(cmdJson); } } catch (Exception e) { logger.log(Level.SEVERE, e.getMessage(), e); sem.release(); } } @Override public void onClose(Session s, CloseReason reason) { logger.info("onClose"); sem.release(); } @Override public void onMessage(String m, Session session) { logger.info("onMessage " + m); String sid = session.getId(); List<String> sl = logsToSync.get(sid); String cmd = "OK;delete;"; if (m.startsWith(cmd)) { String id = m.substring(cmd.length()); try { attLogsManager.remove(id); if (sl != null) { sl.remove(id); } if (sl == null || sl.size() <= 0) { sem.release(); } } catch (AttLogException e) { logger.log(Level.SEVERE, e.getMessage(), e); sem.release(); } } } }); final URI uri = URI.create("ws://" + serverData.getIp() + ":" + serverData.getPort() + serverData.getUrl()); while (true) { // busco a ver si existen logs a ser sincronizados. logs.clear(); try { List<String> ls = attLogsManager.findAll(); if (ls != null && ls.size() > 0) { logs.addAll(ls); sem.drainPermits(); logger.info("connecting to : " + uri.toString()); ContainerProvider.getWebSocketContainer().connectToServer(gwc, uri); try { sem.acquire(); } catch (InterruptedException e1) { e1.printStackTrace(); } } } catch (DeploymentException | AttLogException e) { logger.log(Level.SEVERE, e.getMessage(), e); } catch (IOException e) { logger.log(Level.SEVERE, e.getMessage(), e); } catch (Exception e) { logger.log(Level.SEVERE, e.getMessage(), e); } // limpio todas las sesiones que hayan quedado habiertas. for (Session s : sessions) { try { if (s.isOpen()) { s.close(); } } catch (IOException e) { } } sessions.clear(); logsToSync.clear(); logs.clear(); try { // espero a que alguien marque o hasta que se cumpla el sleep. MutualExclusion.using[MutualExclusion.NEED_ATTLOGS_SYNC].tryAcquire( sleep, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { } } }
/** Send the message divide in packets of Size 1000 */ private void sendDividedChain(final String message) throws IOException { /* * Number of packets to send of Size 1000 */ int ref = message.length() / 1000; /* * Used to validate if the packet is send complete or in two parts */ int residue = message.length() % 1000; /* * Index to handle the send of packet subString */ int beginIndex = 0; int endIndex = 1000; for (int i = 0; i < ref - 1; i++) { if (clientConnection != null && clientConnection.isOpen()) { clientConnection .getBasicRemote() .sendText(message.substring(beginIndex, endIndex), Boolean.FALSE); beginIndex = endIndex; endIndex = endIndex + 1000; } else { raiseClientConnectionCloseNotificationEvent(); } } /* * we get the last Chain to send */ String lastChain = message.substring(beginIndex, message.length()); /* * if residue is equals 0 then send the lastChain Complete * else then the lastChain is divided in two parts to send */ if (residue == 0) { /* * the lastChain is send Complete */ clientConnection.getBasicRemote().sendText(lastChain, Boolean.TRUE); } else { /* * the lastChain is divided in two parts to send */ int middleIndexLastChain = (lastChain.length() % 2 == 0) ? (lastChain.length() / 2) : ((lastChain.length() + 1) / 2) - 1; clientConnection .getBasicRemote() .sendText(lastChain.substring(0, middleIndexLastChain), Boolean.FALSE); clientConnection .getBasicRemote() .sendText(lastChain.substring(middleIndexLastChain, lastChain.length()), Boolean.TRUE); } }
@Override public boolean isConnected() { return websocketSession != null ? websocketSession.isOpen() : false; }