Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHPで作るWebSocketサーバー ~リアクティブなアプリケーションを知るために~...

PHPで作るWebSocketサーバー ~リアクティブなアプリケーションを知るために~ / WebSocket Server in PHP - To know reactive applications

PHP Conference Japan 2024
https://phpcon.php.gr.jp/2024

shiro seike

December 22, 2024
Tweet

More Decks by shiro seike

Other Decks in Programming

Transcript

  1. ©Fusic Co., Ltd. 2 ਗ਼Ո ࢙࿠ @seike460 AWS Community Builder

    Serverless AWS User Group Leaders Community Organizer ɹFukuoka.php ɹFukuoka.go ɹJAWS-UG Fukuoka ɹServerless Meetup Fukuoka ɹCloudflare Meetup Fukuoka ɹJP_Stripes Fukuoka ࣗݾ঺հ ͸͡Ίʹ גࣜձࣾFusic ϓϦϯγύϧΤϯδχΞ/ΤόϯδΣϦετ
  2. ©Fusic Co., Ltd. 3 CONTENTS ໨࣍ 1. WebSocketϋϯυγΣΠΫ 2. WebSocketϑϨʔϜަ׵

    3. JavaScriptଆͷ࣮૷ 4. PHPଆͷ࣮૷ 5. σϞ 6. ·ͱΊ
  3. ©Fusic Co., Ltd. 5 WebSocketͷ֓ཁ ૒ํ޲௨৴ 'VMM%VQMFY HTTP / 01

    ίωΫγϣϯͷҡ࣋ 一 立 立 02 ௿Φʔόʔϔου HTTP 高 用 03 5
  4. ©Fusic Co., Ltd. 6 WebSocketϋϯυγΣΠΫ 6 Client server Request GET

    /chat HTTP/ 1 . 1 Host: example.com: 80 00 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub 2 5 jZQ== Sec-WebSocket-Version: 13 HTTP௨৴ͷҰͭͰ͸͋ΔͷͰɺ HTTPϔομʔΛ֬ೝ
  5. ©Fusic Co., Ltd. 7 WebSocketϋϯυγΣΠΫ 7 Client server Request GET

    /chat HTTP/ 1 . 1 Host: example.com: 80 00 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub 2 5 jZQ== Sec-WebSocket-Version: 13 GETͰɺ/chatʹɺHTTP/1.1Ͱ઀ଓ Hostͷexample.comʹରͯ͠8000൪ϙʔτͰ઀ଓ
  6. ©Fusic Co., Ltd. 8 WebSocketϋϯυγΣΠΫ 8 Client server Request GET

    /chat HTTP/ 1 . 1 Host: example.com: 80 00 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub 2 5 jZQ== Sec-WebSocket-Version: 13 HTTP͔ΒWebSocket΁ͷϓϩτίϧ੾Γସ͑Λཁٻ ʮ੾Γସ͍͑ͨϓϩτίϧͷछྨʯΛࢦఆ
  7. ©Fusic Co., Ltd. 9 WebSocketϋϯυγΣΠΫ 9 Client server Request GET

    /chat HTTP/ 1 . 1 Host: example.com: 80 00 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub 2 5 jZQ== Sec-WebSocket-Version: 13 ϓϩτίϧͷΞοϓάϨʔυΛࣔ͢ ʮϓϩτίϧΛ੾Γସ͑ΔҙࢥʯΛ఻͑Δ Connection: closeͳͲ΋͋Δʢ઀ଓΛऴྃ͢Δҙࢥʣ
  8. ©Fusic Co., Ltd. 10 WebSocketϋϯυγΣΠΫ 10 Client server Request GET

    /chat HTTP/ 1 . 1 Host: example.com: 80 00 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub 2 5 jZQ== Sec-WebSocket-Version: 13 16όΠτҎ্ΛBase64Τϯίʔυͨ͠΋ͷ ΫϥΠΞϯτ͕͜ͷ஋Λࣗ༝ʹੜ੒Մೳ ੜ੒نଇ͕ఆΊΒΕ͍ͯΔΘ͚Ͱ͸͋Γ·ͤΜ
  9. ©Fusic Co., Ltd. 11 WebSocketϋϯυγΣΠΫ 11 Client server Request GET

    /chat HTTP/ 1 . 1 Host: example.com: 80 00 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub 2 5 jZQ== Sec-WebSocket-Version: 13 WebSocketͷVersionΛࣔ͠·͢ αʔόʔ͕ड৴ͨ͠σʔλΛղऍग़དྷΔ͔֬ೝ ղऍͰ͖ͳ͍৔߹͸઀ଓΛ҆શʹऴྃ͢Δ
  10. ©Fusic Co., Ltd. 12 WebSocketϋϯυγΣΠΫ 12 Client server Response Request

    HTTP/ 1 . 1 1 01 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s 3 pPLMBiTxaQ 9 kYGzzhZRbK+xOo= RequestΛड͚ͯɺServer͕ResponseΛฦ٫
  11. ©Fusic Co., Ltd. 13 WebSocketϋϯυγΣΠΫ 13 Client server Response Request

    HTTP/ 1 . 1 1 01 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s 3 pPLMBiTxaQ 9 kYGzzhZRbK+xOo= 101 Switching Protocolsͱͯ͠ɺ Clientͷཁٻͨ͠Protocolʹ੾Γସ͑ΔࣄΛྃঝɺฦ౴
  12. ©Fusic Co., Ltd. 14 WebSocketϋϯυγΣΠΫ 14 Client server Response Request

    HTTP/ 1 . 1 1 01 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s 3 pPLMBiTxaQ 9 kYGzzhZRbK+xOo= Requestͱಉ༷ WebSocketʹUpgrade͢Δ͜ͱΛฦ౴
  13. ©Fusic Co., Ltd. 15 WebSocketϋϯυγΣΠΫ 15 Client server Response Request

    HTTP/ 1 . 1 1 01 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s 3 pPLMBiTxaQ 9 kYGzzhZRbK+xOo= ᶃΫϥΠΞϯτ͕ Sec-WebSocket-Key ͱͯ͠ૹ৴
  14. ©Fusic Co., Ltd. 16 WebSocketϋϯυγΣΠΫ 16 Client server Response Request

    HTTP/ 1 . 1 1 01 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s 3 pPLMBiTxaQ 9 kYGzzhZRbK+xOo= ᶃΫϥΠΞϯτ͕ Sec-WebSocket-Key ͱͯ͠ૹ৴ ᶄWebSocket࢓༷Ͱఆٛ͞ΕͨݻఆGUIDΛ࿈݁ 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ↓ dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
  15. ©Fusic Co., Ltd. 17 WebSocketϋϯυγΣΠΫ 17 Client server Response Request

    HTTP/ 1 . 1 1 01 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s 3 pPLMBiTxaQ 9 kYGzzhZRbK+xOo= ᶃΫϥΠΞϯτ͕ Sec-WebSocket-Key ͱͯ͠ૹ৴ ᶄWebSocket࢓༷Ͱఆٛ͞ΕͨݻఆGUIDΛ࿈݁ ᶅ࿈݁ͨ͠จࣈྻΛSHA-1ͰϋογϡԽ b"\xB3z\xCB0\x98O\x16\x90\xF6F\x18\xCE\x38Y\x16\xB2\x94\xEA\x82\x9F"
  16. ©Fusic Co., Ltd. 18 WebSocketϋϯυγΣΠΫ 18 Client server Response Request

    HTTP/ 1 . 1 1 01 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s 3 pPLMBiTxaQ 9 kYGzzhZRbK+xOo= ᶃΫϥΠΞϯτ͕ Sec-WebSocket-Key ͱͯ͠ૹ৴ ᶄWebSocket࢓༷Ͱఆٛ͞ΕͨݻఆGUIDΛ࿈݁ ᶅ࿈݁ͨ͠จࣈྻΛSHA-1ͰϋογϡԽ ᶆϋογϡԽ͞Εͨ݁ՌΛBase64ͰΤϯίʔυ s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
  17. ©Fusic Co., Ltd. 20 WebSocketϑϨʔϜ 20 Client server Response Request

    8 1 85 37 FA 2 1 3 D 7 F 9 F 4 D 5 1 5 8 - Socket௨৴ - ωοτϫʔΫ্ͰσʔλΛૹड৴͢Δ࢓૊Έ ΫϥΠΞϯτͱαʔόʔؒͷ૒ํ޲௨৴Λ࣮ݱ - WebSocketϑϨʔϜ - SocketͷதͰWebSocketϑϨʔϜΛަ׵ ϔομʔ΍ϖΠϩʔυʢ࣮ࡍͷσʔλʣΛ௨৴
  18. ©Fusic Co., Ltd. 21 WebSocketϑϨʔϜ 21 Client server Response Request

    8 1 85 37 FA 2 1 3 D 7 F 9 F 4 D 5 1 5 8 ϋϯυγΣΠΫ׬ྃޙɺΫϥΠΞϯτͱαʔόʔ͸ ্هͷΑ͏ͳόΠφϦσʔλͷަ׵Λߦ͍·͢ ϝοηʔδ͕ "Hello" ͷ৔߹ 81: FIN=1, OPCODE=1 (ςΩετϑϨʔϜ) 85: MASK=1, ϖΠϩʔυ௕=5 37 FA 21 3D: ϚεΫΩʔ 7F 9F 4D 51 58: ϚεΫ͞Εͨσʔλ
  19. ©Fusic Co., Ltd. 22 WebSocketϑϨʔϜ 22 Client server Response Request

    8 1 85 37 FA 2 1 3 D 7 F 9 F 4 D 5 1 5 8 81: FIN=1, OPCODE=1 (ςΩετϑϨʔϜ) FIN=1ͷ৔߹͸ɺ͜ͷϑϨʔϜ͕ϝοηʔδͷ࠷ޙ FIN=0ͷ৔߹͸ɺ·ͩଓ͖ͷϑϨʔϜ͕͋ΔࣄΛࣔ͢ OPCODE=1ͳͷͰςΩετϑϨʔϜͰ͋ΔࣄΛࣔ͢ ϝοηʔδͷ࠷ޙͷςΩετϑϨʔϜͰ͋Δ
  20. ©Fusic Co., Ltd. 23 WebSocketϑϨʔϜ 23 Client server Response Request

    8 1 85 37 FA 2 1 3 D 7 F 9 F 4 D 5 1 5 8 81: FIN=1, OPCODE=1 (ςΩετϑϨʔϜ) OPCODE (4Ϗοτ)ʹ͸ҎԼͷϑϨʔϜ͕͋Γ·͢ 0x1: ςΩετϑϨʔϜ 0x2: όΠφϦϑϨʔϜ 0x8: ઀ଓͷऴྃ 0x9: Ping 0xA: Pong
  21. ©Fusic Co., Ltd. 24 WebSocketϑϨʔϜ 24 Client server Response Request

    8 1 85 37 FA 2 1 3 D 7 F 9 F 4 D 5 1 5 8 85: MASK=1, ϖΠϩʔυ௕=5 MASK (1Ϗοτ):σʔλ͕ϚεΫ͞Ε͍ͯΔ͔Λࣔ͢ ΫϥΠΞϯτ͔Βૹ৴͞ΕΔϑϨʔϜ͸ ඞͣϚεΫ͞Ε͍ͯΔ (1) αʔόʔ͔ΒͷϑϨʔϜ͸௨ৗϚεΫ͞Εͳ͍ (0)
  22. ©Fusic Co., Ltd. 25 WebSocketϑϨʔϜ 25 Client server Response Request

    8 1 85 37 FA 2 1 3 D 7 F 9 F 4 D 5 1 5 8 85: MASK=1, ϖΠϩʔυ௕=5 Payload Len (7Ϗοτ) :ϖΠϩʔυͷ௕͞Λࣔ͢ 0 ~ 125: ࣮ࡍͷϖΠϩʔυ௕ 126: ࣍ͷ2όΠτ͕ϖΠϩʔυ௕Λࣔ͢(16Ϗοτ੔਺) 127: ࣍ͷ8όΠτ͕ϖΠϩʔυ௕Λࣔ͢(64Ϗοτ੔਺)
  23. ©Fusic Co., Ltd. 26 WebSocketϑϨʔϜ 26 Client server Response Request

    8 1 85 37 FA 2 1 3 D 7 F 9 F 4 D 5 1 5 8 37 FA 21 3D: ϚεΫΩʔ Masking Key (4όΠτ):ϖΠϩʔυσʔλΛ ϚεΫ͢ΔͨΊͷϥϯμϜͳΩʔ ΫϥΠΞϯτૹ৴࣌ͷΈؚ·ΕΔʢޮ཰Խͷҝʣ αʔόʔଆ͸ϚεΫΩʔΛऔಘͯ͠ϚεΫղআ͢Δ தؒϓϩΩγ͕σʔλΛޡղऍ͠ͳ͍Α͏ʹ ϚεΫΛద༻
  24. ©Fusic Co., Ltd. 27 WebSocketϑϨʔϜ 27 Client server Response Request

    8 1 85 37 FA 2 1 3 D 7 F 9 F 4 D 5 1 5 8 7F 9F 4D 51 58ɿPayload Data (ϚεΫ͞Εͨσʔλ) ϚεΫ͞ΕͨσʔλͰ͢ HelloΛϚεΫΩʔΛར༻ͯ͠XORԋࢉ͞Ε͓ͯΓɺ αʔόʔ͸ϧʔϧʹج͍ͮͯϚεΫΛղআͯ͠ɺ ϖΠϩʔυΛར༻͠·͢
  25. ©Fusic Co., Ltd. 28 ௕͍ϖΠϩʔυ (>125όΠτ) ͷ WebSocket ϑϨʔϜ 28

    Client server Response Request 8 1 FE 00 C 8 1 2 34 5 6 7 8 125όΠτΑΓ௕͍ϖΠϩʔυͷ৔߹ɺ ϔομʔͱϖΠϩʔυΛ෼ׂ ҎԼ͸126όΠτͣͭɺ200όΠτͷσʔλΛૹ৴ 81: FIN=1, OPCODE=1ʢςΩετϑϨʔϜʣ FE: MASK=1, ϖΠϩʔυ௕=126 00 C8: ֦ுϖΠϩʔυ௕=200ɹ 12 34 56 78: ϚεΫΩʔ
  26. ©Fusic Co., Ltd. 29 PingϑϨʔϜ 29 Client server Response Request

    8 9 81 12 34 56 78 89: FIN=1, OPCODE=9ʢPingϑϨʔϜʣ 81: MASK=1, ϖΠϩʔυ௕=1 12 34 56 78: ϚεΫΩʔ ϖΠϩʔυ͸ͳ͠
  27. ©Fusic Co., Ltd. 34 JavaScriptଆͷ࣮૷ const WEBSOCKET_URL = "ws://localhost:8080" socket

    = new WebSocket(WEBSOCKET_URL) socket.send(payload) -> ઀ଓઌͷSocket΁ॻ͖ࠐΈ(PHPαʔόʔʹॻࠐΈ) socket.onopen = function (event) {} WebSocketͷ઀ଓ͕੒ޭͨ͠ͱ͖ʹݺͼग़͞Ε·͢ socket.onmessage = function (event) {} αʔόʔ͔ΒϝοηʔδΛड৴ͨ͠ͱ͖ʹݺͼग़͞Ε·͢ socket.onerror = function (error) {} WebSocket઀ଓͰΤϥʔ͕ൃੜͨ͠ͱ͖ʹݺͼग़͞Ε·͢ socket.onclose = function (event) {} WebSocket઀ଓ͕ด͡ΒΕͨͱ͖ʹݺͼग़͞Ε·͢
  28. ©Fusic Co., Ltd. 35 JavaScriptଆͷ࣮૷ socket.onopen = function (event) {}

    WebSocketͷ઀ଓ͕੒ޭͨ͠ͱ͖ʹݺͼग़͞Ε·͢ eventΦϒδΣΫτͷத਎ʹ͸ҎԼ͕ೖ͍ͬͯ·͢
  29. ©Fusic Co., Ltd. 36 JavaScriptଆͷ࣮૷ socket.onmessage = function (event) {}

    αʔόʔ͔ΒϝοηʔδΛड৴ͨ͠ͱ͖ʹݺͼग़͞Ε·͢ eventΦϒδΣΫτͷத਎ʹ͸ҎԼ͕ೖ͍ͬͯ·͢
  30. ©Fusic Co., Ltd. 37 JavaScriptଆͷ࣮૷ socket.onerror = function (error) {}

    WebSocket઀ଓͰΤϥʔ͕ൃੜͨ͠ͱ͖ʹݺͼग़͞Ε·͢ ErrorΦϒδΣΫτͷத਎ʹ͸ҎԼ͕ೖ͍ͬͯ·͢
  31. ©Fusic Co., Ltd. 38 JavaScriptଆͷ࣮૷ socket.onclose = function (event) {}

    WebSocket઀ଓ͕ด͡ΒΕͨͱ͖ʹݺͼग़͞Ε·͢ eventΦϒδΣΫτͷத਎ʹ͸ҎԼ͕ೖ͍ͬͯ·͢
  32. ©Fusic Co., Ltd. 50 σʔλड৴(σίʔυ)ͱϋϯυγΣΠΫ ▪·ͩHandshakeͯ͠ͳ͍Client͔Βͷ௨৴ -> Handshakeཁٻ WebSocket઀ଓͷॳظஈ֊ͰHTTP͔ΒWebSocket΁ͷϓϩτίϧ੾Γସ͑ ࣗ࡞ͷperformHandshake

    ؔ਺ʢޙड़ʣͰHandshakeΛ࣮ࢪ ▪HandshakeࡁΈͷClient͔Βͷ௨৴ -> σʔλ͕ૹ৴͞Ε͖͍ͯͯΔ WebSocketͷϑϨʔϜΛdecodeؔ਺ʢޙड़ʣΛར༻ͯ͠ཧղͰ͖ΔΑ͏ʹ
  33. ©Fusic Co., Ltd. 58 ड৴σʔλͷσίʔυ ord($data[1]) & 127 ͰجຊϖΠϩʔυ௕Λऔಘ 126

    ·ͨ͸ 127 ͷ৔߹ʹ֦ுϖΠϩʔυ௕ΛಡΈऔΔ ֦ுϖΠϩʔυ௕ͷޙʹ͋Δ ϚεΫΩʔʢ4όΠτʣ ΛಡΈऔΓɺ ϖΠϩʔυσʔλ։࢝ҐஔΛܭࢉ
  34. ©Fusic Co., Ltd. 62 Ϋϥ΢υʹ·͔ͤͪΌ͏ͷ΋ख Amazon API Gateway ΋WebSocketରԠͯ͠ΔͷͰ AWS

    Lambda + BrefͳσϞ͕࡞੒ग़དྷΔϦϙδτϦ΋͋Γ·͢ͷͰ ࢼͯ͠Έ͍ͯͩ͘͞ https://github.com/seike460/php-websocket-bref