Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
WebSocket ¿ª·¢Ö¸ÄÏ
 
×÷Õߣºhyerty À´Ô´£º°¢ÀïÔÆ ·¢²¼ÓÚ£º2017-2-16
  3881  次浏览      27
 

HTTP ЭÒé¼òÊö

ÎÒÃÇÏÈÀ´¿´¿´ HTTP¡£

Ò»´Î HTTP ÇëÇó¹ý³ÌÈçÏÂ:

TCP Á¬½ÓÊÇÖ§³ÖË«Ïòͬʱ¶ÁдµÄȫ˫¹¤Ð­Òé, µ«ÊÇÎÒÃÇ¿´´«Í³µÄ HTTP ЭÒéÓм¸¸öÎÊÌâ:

ÇëÇó¹ý³ÌÊÇ´®ÐеÄ, ¿Í»§¶ËÓë·þÎñÆ÷»¥ÏàµÈ´ý.

ÇëÇóÊǵ¥ÏòµÄ, ×ÜÊDZØÐë¿Í»§¶ËÏÈ·¢ÆðÇëÇó.

Ò²¾ÍÊÇ˵, ´«Í³µÄ HTTP 1.0/1.1 ЭÒéûÓгä·ÖÀûÓà TCP Á¬½ÓµÄÄÜÁ¦.

HTTP ЭÒéÊÇÎÞ״̬µÄ, Á½¸öÇëÇóÊÇ´Óͬһ¸ö TCP Á¬½Ó·¢¹ýÀ´, »¹ÊÇ´Ó²»Í¬µÄ TCP Á¬½Ó·¢¹ýÀ´, ¶Ô·þÎñÆ÷À´ËµÓ¦¸ÃÊǵȼ۵Ä.

HTTP ЭÒéÕâÑùµÄÉè¼ÆÖ÷ÒªÊǼò»¯Á˱à³ÌÄ£ÐÍ, ÏëÒ»Ï봫ͳµÄ CGI ½Å±¾, Ò»¸ö½Å±¾Ö»ÒªÄܹ»½ÓÊÜÊäÈë, ²úÉúÊä³ö, ¾Í¿ÉÒÔÌṩ web ·þÎñ¡£HTTP ЭÒéȱÉÙ ISO 7 ²ãÍøÂçÄ£ÐÍÖеĻỰ²ã, ¶¯Ì¬ web Ó¦ÓÃʹÓà cookie À´±£´æ»á»°ÐÅÏ¢¡£HTTP/1.1 ĬÈÏ¿ªÆô³¤Á¬½ÓÀ´ÓÅ»¯ÐÔÄÜ, µ« HTTP Á¬½ÓºÍÇëÇóÒÀÈ»ÊÇÎÞ״̬µÄ¡£¶Ô´«Í³Ìṩ¾²Ì¬ÄÚÈÝ·þÎñ, »ò·µ»ØÐÅÏ¢Ïà¶ÔÈ·¶¨µÄ web Ó¦ÓöøÑÔ, ÕâÑùµÄÉè¼Æ²¢Ã»ÓÐÎÊÌâ, »òÕß˵ËäÈ»ÓÐһЩ²»×ã, µ«ÉÐÄÜÈÌÊÜ¡£ÎÞ״̬µÄÉè¼ÆÒ²¼ò»¯ÁË HTTP ²âÊÔ, ÈÕÖ¾»Ø·ÅÒ²³ÉÎªÖØÒªµÄ HTTP ·þÎñ²âÊÔÊÖ¶ÎÖ®Ò»¡£

websocket ЭÒé¼òÊö

Ö±µ½ "·þÎñÆ÷ÍÆ" ³¡¾°µÄ³öÏÖ¡£·þÎñÆ÷¶ËÐÅÏ¢ËæÊ±¿ÉÄܱ仯, ÎÒÃÇÏ£Íû½«±ä»¯ºó×îеÄÐÅÏ¢Á¢¼´Í¨Öª¸ø¿Í»§¶Ë¡£´«Í³µÄ½â¾ö·½°¸Êǿͻ§¶Ë²»¶ÏÂÖѯ·þÎñÆ÷, ÈçÿÃë 1 ´Î¡£ÕâÖÖÂÖѯ½«²úÉúÐí¶à¶îÍâµÄ´ú¼Û, °üÀ¨Òƶ¯¶ËÁ÷Á¿ÊÕ·Ñ, ²¢ÇÒ±à³ÌÄ£ÐÍÒ²Ïà¶Ô¸´ÔÓ¡£Òò´Ë, ÊÇʱºò¿ª·Å TCP Ë«ÏòͨÐŵÄÄÜÁ¦ÁË¡£ÎÒÃÇ¿ÉÒÔÖØÐÂдһ¸ö TCP ·þÎñÆ÷, ʹÓÃеÄЭÒéÀ´Í¨ÐÅ¡£µ«Ò²ÐíÊÇΪÁ˸´Óà HTTP µÄ 80 ¶Ë¿Ú, ÒÀ¸½ÏÖÓÐ HTTP Éú̬Ȧ, Èà web Ó¦ÓÃÆ½»¬Éý¼¶, websocket »ùÓÚ HTTP ЭÒéÉè¼Æ, ¹ËÃû˼Òå¾ÍÊÇ»ùÓÚ web HTTP ЭÒé, ÊÍ·ÅÔ­Éú TCP socket µÄÄÜÁ¦¡£ËùÒÔ websocket Ò»¿ªÊ¼»¹Êǰ´ HTTP ЭÒéͨÐÅ, Ëæºó²Åת»»³É websocket¡£

Ò»¸ö websocket Á¬½ÓµÄ½¨Á¢¹ý³ÌÈçÏÂ:

websocket ¿É»ùÓÚ HTTP ½¨Á¢, ¼´ ws ЭÒé, Ò²¿É»ùÓÚ HTTPS ½¨Á¢, ¼´ wss ЭÒé, ¹ûÈ»ÊǸ´ÓÃÁË HTTP µÄ»ù´¡ÉèÊ©¡£

HTTP Óë websocket ¿Í»§¶Ë

HTTP ¿Í»§¶Ë·¢ËÍÍêÇëÇóºó²Å»á¼àÌýÏìÓ¦, ÊÕµ½Ò»´ÎÏìÓ¦ºó¼´½áÊø¡£³£¼ûµÄ HTTP ¿Í»§¶ËÓÐ:

1.curl, Èç curl localhost:8080/http.

2.ä¯ÀÀÆ÷ js ¿Í»§¶Ë, Èç angularjs µÄ $http ·þÎñ.

$http.get("/http").then(function(resp) {
vm.msg = resp.data;
});

3.Ö±½ÓÔÚä¯ÀÀÆ÷ÊäÈë URL.

»Ø¹Ë "·þÎñÆ÷ÍÆ" ³¡¾°, websocket Óë HTTP ЭÒé×î´óµÄ²»Í¬ÔÚÓÚ·þÎñÆ÷²»±ØµÈ´ýÇëÇó, Ò²²»ÔÙʹÓà "ÇëÇó", "ÏìÓ¦" ÕâÑùµÄÊõÓï, ¶ø¸Ä³ÆÎªÏûÏ¢, Ë«·½¶¼¿ÉÒÔËæÊ±»¥·¢ÏûÏ¢¡£HTTP ¿Í»§¶Ë²»»áÒ»Ö±¼àÌýÏûÏ¢, ËùÒÔÏÔÈ»²»ÄÜ×÷Ϊ websocket ¿Í»§¶Ë (ÇÒ²»ËµÐ­ÒéÊÇ·ñ¼æÈÝ)¡£ÒªÊ¹Óà websocket, ¿Í»§¶ËºÍ·þÎñÆ÷¶¼ÐèÒª¸ÄÔì¡£³£¼ûµÄ websocket ¿Í»§¶ËÓÐ:

1.ä¯ÀÀÆ÷ js ¿Í»§¶Ë¡£¸Ðлä¯ÀÀÆ÷³§ÉÌ, ÏÖÔÚµÄÖ÷Á÷ä¯ÀÀÆ÷¶¼Ö§³Ö websocket ¡£

²Î¿¼: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket

var uri = "ws://" + window.location.host + "/ws";
vm.ws = new WebSocket(uri);
vm.ws.onmessage = function(event) {
vm.msg = event.data;
$scope.$apply();
}

websocket ·þÎñ¶Ë¿ª·¢

ÔÙÀ´¿´·þÎñ¶Ë¿ª·¢, java ¶¨ÒåÁËÒ»Ì× javax.servlet-api, Ò»¸ö HttpServlet ¾ÍÊÇÒ»¸ö HTTP ·þÎñ¡£java websocket ²¢·Ç»ùÓÚ servlet-api ¼òµ¥À©Õ¹, ¶øÊÇж¨ÒåÁËÒ»Ì× javax.websocket-api¡£Ò»¸ö websocket ·þÎñ¶ÔÓ¦Ò»¸ö Endpoint¡£Óë ServletContext ¶ÔÓ¦, websocket-api Ò²¶¨ÒåÁË WebSocketContainer, ¶ø±à³Ì·½Ê½×¢²á websocket µÄ½Ó¿ÚÊǼ̳Ð×Ô WebSocketContainer µÄ ServerContainer¡£Ò»¸ö websocket ¿ÉÒÔ½ÓÊܲ¢¹ÜÀí¶à¸öÁ¬½Ó, Òò´Ë¿É±»ÊÓ×÷Ò»¸ö server¡£Ö÷Á÷ servlet ÈÝÆ÷¶¼Ö§³Ö websocket, Èç tomcat, jetty µÈ¡£¿´ ServerContainer api Îĵµ, ¿É´Ó ServletContext attribute ÕÒµ½ ServerContainer¡£

@Bean
public ServerContainer serverContainer(ServletContext context) {
return (ServerContainer) context.getAttribute(ServerContainer.class.getName());
}

×¢²á Endpoint ¹Ø¼üÐèÒªÁ½¸ö¶«Î÷, Endpoint ÀàºÍ¶ÔÓ¦ URL ·¾¶, ´úÂëÈçÏÂ:

@org.springframework.context.annotation.Configuration
public class WsConfig implements ApplicationRunner {

@Autowired
protected ServerContainer serverContainer;

@Override
public void run(ApplicationArguments args) throws Exception {
ServerEndpointConfig sec = ServerEndpointConfig.Builder.create(Ws.class, "/ws").build();
serverContainer.addEndpoint(sec);
}

}

Ò»¸ö¼òµ¥ servlet ʾÀýÈçÏÂ:

public class Http extends HttpServlet {

private static final long serialVersionUID = 1L;

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = "Hello Http";
resp.setContentType(MimeTypeUtils.TEXT_PLAIN_VALUE);
resp.getWriter().println(msg);
}

}

Ò»¸ö¼òµ¥ Endpoint ʾÀýÈçÏÂ:

public class Ws extends Endpoint {

@Override
public void onOpen(Session session, EndpointConfig config) {
String msg = "Hello WebSocket";
Basic remote = session.getBasicRemote();
try {
remote.sendText(msg);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}

}

Á½ÕßÃ²ËÆÏàËÆ, ÆäʵÓкܴó²»Í¬¡£

1.doGet() ÊÇ´¦ÀíÒ»´ÎÇëÇó, ÊäÈë²ÎÊý req ºÍ resp Ò»´ÎÓÐЧ, ±¾´ÎÇëÇ󷵻ؼ´Ê§Ð§¡£

2.onOpen() ÊÇ´ò¿ª websocket »á»°, ÊäÈë²ÎÊý session »á»°ÄÚÒ»Ö±ÓÐЧ, ¿ÉÊÕ·¢¶à´ÎÏûÏ¢¡£ ʾÀýÖлỰ´ò¿ªºó¼´·¢Ë͵ÚÒ»ÌõÏûÏ¢¡£

3.Endpoint ÊÇÓÐ״̬µÄ, ÈÝÆ÷Ϊÿ¸ö»á»°´´½¨Ò»¸ö Endpoint ¶ÔÏóʵÀý, ά»¤µ±Ç°»á»°×´Ì¬ÐÅÏ¢¡£ ËùÒÔ×¢²á Endpoint ±ØÐëʹÓÃÀà¶ø²»ÄÜʹÓöÔÏó, ÇÒ Endpoint Àà±ØÐëÓÐÎ޲ι¹½¨º¯Êý¡£ ¶ø Servlet ÊÇÎÞ״̬µÄ, ¿ÉÒÔʹÓà Servlet ʵÀý×¢²á, ¶àÁ¬½Ó¶àÏ߳̾ùÖ»ÓÐÒ»¸ö Servlet ¶ÔÏóʵÀý¡£

4.websocket Á¬½ÓÊÇÓÐ״̬µÄ, ±ØÐëʹÓó¤Á¬½Ó, Ò»¸öÁ¬½ÓÌìÈ»¾ÍÊÇÒ»¸ö»á»° session¡£ HTTP Á¬½ÓÊÇÎÞ״̬µÄ, Servlet ½èÖú cookie ¹ÜÀí»á»°, ¶ÔÊÇ·ñ³¤Á¬½ÓÎÞ¸ÐÖª¡£ ×¢Òâ: websocket ³¤Á¬½ÓÓë HTTP ³¤Á¬½ÓÓкܴó²»Í¬¡£ HTTP ³¤Á¬½ÓÖ»ÊÇΪÁËÏòͬһ·þÎñÆ÷·¢ËÍÇëÇóʱ¸´ÓÃÒÑÓÐµÄ TCP Á¬½Ó, ÓÅ»¯ÐÔÄÜ, ·¢ËÍÇëÇó´ø²»Í¬µÄ cookie ¾Í¿ÉÄܹØÁª²»Í¬µÄ HTTP session¡£ Ò»¸ö websocket ³¤Á¬½ÓֻΪһ¸ö»á»°·þÎñ, Ö»ÄÜÊÕ·¢¸Ã»á»°µÄÏûÏ¢¡£ HTTP ³¤Á¬½Óת»¯Îª websocket ºó, ¾Í²»ÄÜÔÙÓÃÓÚ·¢ËÍ HTTP ÇëÇó¡£

5.HTTP ÇëÇóÊÇ´®ÐеÄ, Ò»¸ö HTTP ³¤Á¬½Ó±ØÐëÔÚÉÏÒ»¸öÇëÇóÏìÓ¦·µ»Øºó, ²ÅÄܼÌÐø·¢ËÍÇëÇó¡£ websocket Ë«·½¿ÉÒÔ×ÔÓÉÊÕ·¢ÏûÏ¢, ²»±ØµÈ´ý, ¸ÕÊÕµ½µÄÏûϢδ±ØÓë¸Õ·¢³öÈ¥µÄÏûÏ¢¶ÔÓ¦¡£ ÊÕ·¢ÏûÏ¢µÄº¬ÒåÓ¦¸ÃÔÚ½¨Á¢ websocket Á¬½Óʱ±ãÒѾ­È·ÈÏ¡£

6.ÓÉÓÚ websocket ÊÕ·¢ÏûÏ¢µÄº¬ÒåÔÚ½¨Á¢ websocket Á¬½Óʱ±ãÒѾ­È·ÈÏ, ÊÕ·¢ÏûϢʱ¿ÉÒÔʡȥºÜ¶àÍ·ÐÅÏ¢ºÍ²ÎÊý, °üÀ¨±êʶ»á»°µÄ cookie ÐÅÏ¢, ÓÐЧ½ÚÔ¼´ø¿í¡£

·þÎñ¶Ë´úÂë½áºÏÇ°ÃæµÄ¿Í»§¶Ë´úÂë, ¼´¿É²âÊÔ websocket¡£

ʹÓà curl ²âÊÔ websocket

Ç°ÃæÌáµ½µÄ websocket ¿Í»§¶ËÖ»ÓÐä¯ÀÀÆ÷ js¡£»Ø¹Ë½¨Á¢ websocket Á¬½ÓµÄÁ÷³Ì, ¿Í»§¶ËÖ»ÐèÒª·¢Ò»¶Î HTTP ÇëÇó, ÄÇôÊÇ·ñ¿ÉÒÔʹÓà curl ½¨Á¢ websocket Á¬½ÓÄØ? ¾­²âÊÔÊÇ¿ÉÒÔµÄ, ËùÐè²ÎÊýÐÅÏ¢ÈçÏÂ, ²¢ÇÒ curl Ò²²»»á²»Í£µÄ½ÓÊÕÏìÓ¦ºÍÏûÏ¢¡£

--no-buffer -H 'Connection: keep-alive, Upgrade' -H 'Upgrade: websocket' -v -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: websocket'

curl ĬÈϻỺ³åÇøÂú»ò½ÓÊÕÍêÏìÓ¦²ÅÊä³ö, ÓÉÓÚ websocket ÏìÓ¦ "ÓÀ²»½áÊø", --no-buffer ½ûÓà curl ÄÚ²¿µÄ»º³åÇø, ʹÆäÁ¢¼´Êä³ö½ÓÊÕµ½µÄÐÅÏ¢¡£ÆäËû²ÎÊýΪ¸´ÖÆä¯ÀÀÆ÷½¨Á¢ websocket ʱ·¢ËÍÇëÇóÐÅÏ¢, ɸѡ³öµÄ±ØÐëÐÅÏ¢¡£

ʹÓà curl ²âÊÔ websocket, ½á¹ûÈçÏÂ:

$ curl --no-buffer -H 'Connection: keep-alive, Upgrade' -H 'Upgrade: websocket' -v -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: websocket' http://localhost:8080/ws | od -t c
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /ws HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
> Connection: keep-alive, Upgrade
> Upgrade: websocket
> Sec-WebSocket-Version: 13
> Sec-WebSocket-Key: websocket
>
< HTTP/1.1 101
< Upgrade: websocket
< Connection: upgrade
< Sec-WebSocket-Accept: qVby4apnn2tTYtB1nPPVYUn68gY=
< Date: Tue, 31 Jan 2017 12:31:23 GMT
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0{ [17 bytes data]
0000000 201 017 H e l l o W e b S o c k e
100 32 0 32 0 0 26 0 --:--:-- 0:00:01 --:--:-- 26^C

ÓÉÓÚ websocket ÏûÏ¢º¬Óжþ½øÖÆÍ·²¿, ʹÓà od -t c ½øÐÐתÒå, ÏûϢͷ²¿Îª 201 017 Á½¸ö×Ö½Ú, ÆäÖÐ 017 = 15, Ó¦¸Ã±íʾÏûÏ¢³¤¶È¡£ÏûÏ¢³¤¶ÈʹÓÃÁ˱䳤ÕûÊý±íʾ, ³¤¶È³¬¹ý 127 ʱ»áʹÓöà×Ö½Ú±íʾ³¤¶È¡£ÎÒÃÇ¿´µ½ÏûÏ¢ÌåûÓÐÈ«²¿Êä³ö, ÕâÊÇÒòΪ od ÃüÁîÒ³×öÁË»º³å, ÔÜÂúÒ»ÐвÅÊä³ö, ÐÞ¸ÄΪ od -t c -w1 -v, ¼´Ò»¸ö×Ö½ÚÒ»ÐÐ, ¼´¿É±ÜÃâÕâ¸öÎÊÌâ, µ«Êä³öÏûÏ¢½«±»²ð³ÉºÜ¶àÐС£

-v ±íʾÏÔÊ¾ÖØ¸´ÐÐ, ĬÈÏ»áѹËõÏû³ýÖØ¸´ÐС£

ÉÏÊöÍ·ÐÅÏ¢ÖÐ, Sec-WebSocket-Key ÊÇÓÃÓÚ²âÊÔ·þÎñÆ÷ÊÇ·ñÖ§³Ö websocket, ÏêÇé²Î¿¼ https://tools.ietf.org/html/rfc6455#page-7 ¡£¾­²âÊÔÊäÈëͷʹÓÃÈÎÒâÖµ¾ù¿É, ·þÎñÆ÷·µ»ØÕýÈ·µÄ Sec-WebSocket-Accept ÐÅÏ¢±íʾËüÖ§³Ö websocket, Ç¡µ±µÄ websocket ¿Í»§¶ËÓ¦¸ÃҪУÑéÕâ¸öÖµ¡£

ʹÓà sendText() ʱ, websocket ×Ô¶¯Ìí¼ÓÁËÏûϢͷÐÅÏ¢, ÒÔ×Ô¶¯ÊµÏÖÏûÏ¢·âÖ¡ºÍ²ðÖ¡¡£websocket »¹Ö§³Ö·¢ËͶþ½øÖÆÏûÏ¢»ò·¢ËÍÁ÷ʽÊý¾Ý¡£²âÊÔ·¢ÏÖÒ»¸ö websocket ¿ÉÒÔͬʱ֧³Ö¶þ½øÖƺÍÎı¾ÏûÏ¢ÊÕ·¢¡£µ«µ±ÕýÔÚ·¢ËÍÁ÷ʽÏûϢʱ, ²»ÄÜ·¢ËÍÆäËûÀàÐÍÏûÏ¢¡£

websocket ·¢ËÍÁ÷ʽ¶þ½øÖÆÊý¾Ýʱ, ÊÇ·ñ¿ÉÒÔ×÷ΪԭʼµÄ TCP socket ʹÓÃÄØ? ¼´ÕÕ°áËùÓÐÊý¾Ý, ²»Òª¼ÓÏûÏ¢Ö¡Í·²¿¡£²âÊÔ´úÂëÈçÏÂ:

public class Ws extends Endpoint {

@Override
public void onOpen(Session session, EndpointConfig config) {
byte[] msg = { 'w', 's', };
Basic remote = session.getBasicRemote();
try {
OutputStream out = remote.getSendStream();
for (int i = 0; i < 1; ++i) {
for (int j = 0; j < 4; ++j) {
out.write(msg[j % msg.length]);
}
out.flush();
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}

}

ÆäÖÐÍâ²ãÑ­»·±íʾд¼¸´ÎÊý¾Ý, ÄÚ²ãÑ­»·±íʾÿ´ÎдÊý¾Ý³¤¶È¡£²âÊÔ·¢ÏÖֻдһ´Î²¢ÇÒ³¤¶ÈСÓÚ4ʱ, ¿Í»§¶ËÊÕ²»µ½ÈκÎÊý¾Ý, bug OR Ó÷¨²»¶Ô?

²âÊÔ·¢ÏÖÈçÏÂÎÊÌâ:

1.Êý¾Ý³¤¶ÈºÜС²¢ÇÒ²»µ÷Óà flush() ʱ, ¿Í»§¶ËҲʼÖÕÊÕ²»µ½Êý¾Ý¡£ ÕâÒ²ÊÇÓë servlet ²»Ò»ÑùµÄµØ·½, servlet Õý³£Çé¿öϲ»Ó¦¸Ãµ÷Óà flush(), servlet ·½·¨·µ»ØºóÏìÓ¦¾Í»á·µ»Ø¸ø¿Í»§¶Ë, ÏÔʽµ÷Óà flush() »áµ¼ÖÂÒÔ Chunked ·½Ê½Á¢¼´·µ»Ø²¿·ÖÄÚÈÝ¡£

2.Á÷ʽ·¢ËÍÊý¾ÝÒÀÈ»»áÌí¼ÓÏûϢͷ²¿. od Êä³öÈçÏÂ:

0000000 002
0000001 004
0000002 w
0000003 s
0000004 w
0000005 s

²¢ÇÒ¶à´ÎдÊý¾ÝµÄ»°, ÿ´ÎдÊý¾Ý¶¼»áÌí¼ÓÍ·²¿¡£Ð´ 3 ´Î od Êä³öÈçÏÂ:

0000000 002
0000001 004
0000002 w
0000003 s
0000004 w
0000005 s
0000006 \0
0000007 004
0000010 w
0000011 s
0000012 w
0000013 s
0000014 \0
0000015 004
0000016 w
0000017 s
0000020 w
0000021 s

µÚÒ»´ÎÍ·²¿²»Ò»Ñù, Ö®ºóÿ´ÎÍ·²¿¶¼ÊÇ \0 + Êý¾Ý³¤¶È¡£

3.Ò»´ÎдÊý¾ÝºÜ³¤Ê±, ²»Óõ÷Óà flush() Ò²»á·¢ËÍÊý¾Ýµ½¿Í»§¶Ë (»º³åÇøÂú?),

²¢ÇÒ·¢ËÍÊý¾Ý²ðΪ N ¶Î, ÿ¶Î¶¼»á¼ÓÏûϢͷ¡£

ÎÊÌâ: ÈçºÎ½áÊøÁ÷ʽÏûÏ¢·¢ËÍ?

ÓÉ´Ë¿ÉÖª, websocket ʼÖÕ»á¼ÓÏûϢͷ½øÐзÖÖ¡, ²»ÄÜ×÷ΪԭʼµÄ TCP socket ʹÓá£ÏëÏëÒ²ÊÇ, ²»¼ÓÏûϢͷ websocket Ò²²»ÄÜÇø·ÖÁ÷ʽÊý¾ÝºÍ·ÖÖ¡ÏûÏ¢, ²¢ÇÒÆÕͨÏûÏ¢¼ä»¹¿ÉÒԼдø ping/pong Ó¦ÓòãÐÄÌø¼ì²â¡£Òò´Ë websocket Ó¦¸ÃÊÇÒ»¸öÖ§³ÖÏûÏ¢·âÖ¡ºÍÓ¦ÓòãÐÄÌø¼ì²âµÄ»á»°²ãЭÒé¡£

ÔÚ spring ÖÐʹÓà websocket

spring ¶Ô websocket ÌṩÁ˺ܺõÄÖ§³Ö, ²Î¿¼Îĵµ: https://docs.spring.io/spring/docs/current/ spring-framework -reference/html/websocket.html .

Ç°ÃæÌáµ½ java websocket-api ÒªÇóʹÓà Endpoint class ×¢²á websocket, È»ºóÓÉ Servlet ÈÝÆ÷Ϊÿ¸öÁ¬½Ó´´½¨ Endpoint ¶ÔÏóʵÀý, ÕâÑù¾ÍºÜÄѽ« Endpoint ʵÀýÄÉÈë spring ÈÝÆ÷ÖС£spring ¶Ô websocket µÄ´¦ÀíÓëʹÓà DispatcherServlet ´¦Àí HTTP ÇëÇóÀàËÆ¡£spring ¶¨ÒåÁË WebSocketHandler ½Ó¿Ú´¦Àí websocket ÇëÇó, ÀàËÆ HTTP µÄ HttpRequestHandler¡£È»ºó spring À¹½ØËùÓÐÍÐ¹ÜµÄ websocket ÇëÇó, ·Ö·¢µ½ WebSocketHandler ÉÏ¡£Î¨Ò»µÄȱµãÊÇ WebSocketHandler Óë HttpRequestHandler Ò»ÑùÊÇÎÞ״̬µÄµ¥Àý, ²»ÄÜÖ±½Ó±£´æµ¥¸ö»á»°×´Ì¬, È»¶øÕⲢûÓйØÏµ¡£½ÓÏÂÀ´ÎÒÃǾͿÉÒÔÍü¼Ç java websocket-api, ʹÓà spring websocket API À´±à³ÌÁË¡£

Ç°ÃæÊ¾ÀýµÄ websocket, ʹÓà spring ÖØÐ´ÈçÏÂ:

public class SpringWs extends AbstractWebSocketHandler {

@Override
public void afterConnectionEstablished (WebSocketSession session) throws Exception {
super.afterConnectionEstablished(session);
session.sendMessage(new TextMessage("Hello WebSocket"));
}

}

×¢²á websocket ´úÂëÈçÏÂ:

@Configuration
@EnableWebSocket
public class SpringWsConfig implements WebSocketConfigurer {

@Override
public void registerWebSocketHandlers (WebSocketHandlerRegistry registry) {
registry.addHandler(new SpringWs(), "/ws");
}

}

¿´Ò»Ï AbstractWebSocketHandler ·½·¨¶¨Òå, ÎÒÃÇ·¢ÏÖÉÙÁËÁ÷ʽÊý¾ÝÊÕ·¢´¦Àí, µ«·â×°¼ò»¯ÁË web Ó¦Óó£ÓõÄÏûÏ¢ÊÕ·¢´¦Àí¡£

websocket ÐÄÌø¼ì²â

websocket ÌṩÁËÓ¦ÓòãÐÄÌø¼ì²â, ÓÉ ping/pong ÏûÏ¢×é³É¡£ping ±íʾ "ÄãÔÚÂð?", pong ±íʾ "ÎÒÔÚ!"¡£ping/pong ¶ÔÓ¦ IP µÄ ping ÇëÇóºÍ ping ÏìÓ¦, websocket ²»Ê¹ÓÃÇëÇóÏìӦģʽ, ËùÒÔ¶¼½Ð×öÏûÏ¢¡£websocket Çø·ÖÊý¾ÝÏûÏ¢ºÍ¿ØÖÆÏûÏ¢, Òò´ËÖ»¼àÌýÊý¾ÝÏûÏ¢ÊDz»»áÊÕµ½¿ØÖÆÏûÏ¢µÄ¡£ping/pong ÊôÓÚ¿ØÖÆÏûÏ¢¡£ä¯ÀÀÆ÷ͨ³£²»Ö§³Ö¿ØÖÆ ping/pong ÏûÏ¢, ¶Ô ping Ö±½Ó»Ø¸´ pong, ºöÂÔ pong¡£java websocket-api ºÍ spring ¶¼¶Ô·¢ËÍ ping/pong ÌṩÁËÖ±½ÓÖ§³Ö, ĬÈϺöÂÔ pong¡£

websocket java ¿Í»§¶Ë

websocket Ò»µ©½¨Á¢Á¬½ÓÒÔºó, ¿Í»§¶ËÓë·þÎñÆ÷ÊǶԵȵÄ, ¶¼½Ð Endpoint, Á½¶Ë¿ÉÒÔ¸´ÓÃЭÒé½âÎöºÍÏûÏ¢¼àÌýµÄ´úÂë¡£Òò´Ë java websocket-api Ò²¶¨ÒåÁ˿ͻ§¶Ë API, µ÷Óà WebSocketContainer.connectToServer() ¼´¿É½¨Á¢¿Í»§¶Ëµ½·þÎñÆ÷µÄÁ¬½Ó¡£Ç°ÃæÌáµ½ ServerContainer ¼´ÊÇ WebSocketContainer, ¿Í»§¶ËÒ²¿Éµ÷Óà ContainerProvider.getWebSocketContainer() »ñÈ¡ WebSocketContainer¡£

ʾÀý´úÂëÈçÏÂ:

public class Client {

public static void main(String[] args) throws Exception {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
URI path = new UR ("ws://localhost:8080/ ws");
Session session = container.connectToServer(new Ws(), path);
session.addMessageHandler (new javax.websocket.MessageHandler.Whole< String>() {
@Override
public void onMessage(String message) {
System.out.println("Client get message: " + message);
}
});
Thread.sleep(5000);
}

}

1.java websocket-api ¿Í»§¶Ë´úÂëÊÇ×¢½âµ¼ÏòµÄ, Endpoint Àà±ØÐë¼Ó @ClientEndpoint ×¢½â. onOpen() ·½·¨Ò²±ØÐëÌí¼Ó @OnOpen ×¢½â²Å»áÉúЧ. Endpoint ÀàʹÓÃÆÕͨ POJO À༴¿É.

2.ÓÉÓÚ¿Í»§¶Ë¿ÉÒÔ¿ØÖÆÃ¿Ò»¸öÁ¬½ÓµÄ´´½¨¹ý³Ì, ¿ÉÒÔʹÓà Endpoint ¶ÔÏóʾÀý×÷Ϊ²ÎÊý, ÕâÑùÓ¦¸Ã¸üÈÝÒ×Óë spring ¼¯³É.

3.Endpoint ÀàµÄ×î¼Ñʵ¼ùÓ¦¸ÃÖ»ÓÃÓÚÔڻỰÆÚ¼ä±£´æ»á»°×´Ì¬.

4.websocket ¿Í»§¶Ë²»×èÈû½ø³Ì(ûÓÐǰ̨Ïß³Ì?), Òò´ËʾÀý³ÌÐòÌí¼Ó sleep ±ÜÃâ³ÌÐòÁ¢¼´Í˳ö¡£

5.websocket ¿Í»§¶Ë²»ÒÀÀµ servlet ÈÝÆ÷, ÆÕͨӦÓÃÒ²¿ÉÒÔºÜÈÝÒ×µÄʹÓà websocket¡£

Ö´ÐÐÉÏÊö¿Í»§¶Ë²¢Ã»ÓÐÊÕµ½ÏûÏ¢, ²ÂÏëÊÇÖ´ÐÐ addMessageHandler() ʱÒѾ­ÊÕÍêÏûÏ¢ÁË¡£

Endpoint ÀàÌí¼ÓÏûÏ¢´¦Àí:

@javax.websocket.OnMessage
public void onMessage(String message) {
System.out.println("Endpoint onMessage: " + message);
}

Õâ»ØÖÕÓÚÊÕµ½ÏûÏ¢ÁË, ͬʱ³öÏÖÈçÏÂÒì³£:

Exception in thread "main" java.lang.IllegalStateException: A text message handler has already been configured
at org.apache.tomcat.websocket. WsSession.doAddMessageHandler (WsSession.java:252)
at org.apache.tomcat.websocket.WsSession.addMessageHandler (WsSession.java:213)
at atest.Client.main(Client.java:16)

¿ÉÖª:

1.ÒªÏë²»ÒÅ©ÏûÏ¢, Ó¦ÔÚ Endpoint ÀàÉÏÌí¼ÓÏûÏ¢´¦Àí·½·¨(ʹÓÃ×¢½â), ¶ø addMessageHandler() ÓÃÓÚ¶¯Ì¬Ìí¼ÓÏûÏ¢´¦ÀíÆ÷¡£ È¥µô Endpoint ÀàÉϵÄÏûÏ¢´¦Àí, ·þÎñÆ÷ÑÓʱ·¢ËÍÏûÏ¢, ¿Í»§¶Ë¹ûȻҲÄÜÊÕµ½ÏûÏ¢¡£ »òÕß websocket »á»°Ó¦Óòãά»¤ ready ״̬, ¿Í»§¶Ë³õʼ»¯Íê³ÉÔÙ¸æËß·þÎñ¶Ë ready ¡£

2.Ò»ÖÖÏûÏ¢ÀàÐÍ (Èç String Îı¾ÏûÏ¢) Ö»ÄÜÉèÖÃÒ»¸öÏûÏ¢´¦ÀíÆ÷¡£

spring Ò²¶Ô websocket ¿Í»§¶Ë½øÐÐÁ˼òµ¥·â×°, ²¢ÇÒ¸´ÓÃÁË WebSocketHandler ½Ó¿ÚÉè¼Æ, ½¨Á¢Á¬½ÓµÄºËÐÄÀàÊÇ WebSocketConnectionManager,

ʾÀý´úÂëÈçÏÂ:

public class SpringClient {

public static void main(String[] args) {
SpringApplication app = new SpringApplication(SpringClient.class, SpringWs.class);
app.setApplicationContextClass (AnnotationConfigApplicationContext.class);
WebSocketConnectionManager conn = app.run(args). getBean(WebSocketConnectionManager.class);
conn.start();
}

@Bean
public WebSocketClient webSocketClient() {
return new StandardWebSocketClient();
}

@Bean
public WebSocketConnectionManager conn (WebSocketClient client, WebSocketHandler handler) {
return new WebSocketConnectionManager (client, handler, "ws://localhost:8080/ws");
}

}

¿Í»§¶ËÓë·þÎñÆ÷ʹÓÃÁËÏàͬµÄ WebSocketHandler, ÔËÐÐʾÀý³ÌÐòºó¿Í»§¶ËÓë·þÎñÆ÷¸÷×Ô·¢³ö²¢ÊÕµ½Ò»ÌõÏàͬµÄÏûÏ¢¡£×¢ÒâÕâÀï¿Í»§¶ËûÓÐ sleep, ¿Í»§¶ËÓÅÑÅÍ˳öǰÒѾ­ÊÕµ½ÏûÏ¢¡£

ÐÞ¸Ä WebSocketHandler ·¢ËÍ ping ÏûÏ¢, ´òÓ¡ pong ÏûÏ¢, ²âÊÔ·¢ÏÖ·þÎñÆ÷ºÍ¿Í»§¶Ë¶¼ÊÕµ½Ò»Ìõ pong ÏûÏ¢¡£¿É¼û spring Ò²¶Ô ping ÏûÏ¢×öÁË´¦Àí, ×Ô¶¯»Ø¸´ pong ÏûÏ¢¡£

spring websocket API ÕûÌå¸Ð¾õ±È javax.websocket-api ¸ü¼Ó¼òµ¥Ò»Ö¡£³ýÁËÉÙÁËÁ÷ʽ¶Áд½Ó¿Ú, È»¶øÕâ²¢²»ÖØÒª¡£

 

   
3881 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

¹È¸è½ÌÄãÈçºÎ¹¹½¨Ò»¸öÓÅÐãµÄÒÆ¶¯ÍøÕ¾
ÈçºÎ¸ßЧµØ¹ÜÀíÍøÕ¾¾²Ì¬×ÊÔ´
¸ßÐÔÄÜÍøÕ¾½¨ÉèµÄ×î¼Ñʵ¼ù
Ïл°ÍøÕ¾×ó²àµ¼º½µÄʵÏÖ
 
Ïà¹ØÎĵµ

ÍøÕ¾½¨Éè·½°¸Á÷³Ì
ÍøÕ¾½¨Éècss½Ì³Ì
ÆóÒµÍøÕ¾½¨ÉèÓëÍÆ¹ã
ÍøÕ¾½¨Éè·½°¸Êé
Ïà¹Ø¿Î³Ì

Éè¼ÆÄ£Ê½Ô­ÀíÓëÓ¦ÓÃ
´ÓÐèÇó¹ý¶Éµ½Éè¼Æ
Èí¼þÉè¼ÆÔ­ÀíÓëʵ¼ù
ÈçºÎ±àд¸ßÖÊÁ¿´úÂë