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
¸ü¼Ó¼òµ¥Ò»Ö¡£³ýÁËÉÙÁËÁ÷ʽ¶Áд½Ó¿Ú, È»¶øÕâ²¢²»ÖØÒª¡£
|