{"id":429605,"date":"2024-08-20T15:01:30","date_gmt":"2024-08-20T15:01:30","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=429605"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=429605","title":{"rendered":"<span>\u0417\u0430\u043c\u0435\u0442\u043a\u0430 \u043f\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 WebTransport \u0432 Python \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f aioquic \u0438\u043b\u0438 \u0421\u043a\u0443\u0447\u043d\u044b\u0439 `\u043a\u043b\u0438\u043a\u0435\u0440` \u0441 (\u043d\u0435)\u0441\u043a\u0443\u0447\u043d\u044b\u043c QUIC<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u0442\u0430\u0442\u044c\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u043e\u0439 \u043f\u0440\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 aioquic \u0438 \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f WebTransport. \u0417\u0430\u043c\u0435\u0442\u043a\u0430 \u0431\u044b\u043b\u0430 \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u043a\u0430\u043a \u0440\u0430\u0437\u0431\u043e\u0440 \u0447\u0443\u0436\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043f\u0440\u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0435 \u0441 aioquic. \u0417\u0430\u043c\u0435\u0442\u043a\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f QUIC \u0438 HTTP\/3 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 aioquic, \u043e\u043f\u0438\u0440\u0430\u044f\u0441\u044c \u043d\u0430 \u0441\u0442\u0430\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u0439 \u043f\u0440\u0438\u043c\u0435\u0440. \u0412 \u0445\u0443\u0434\u0448\u0438\u0445 \u0430\u043a\u0430\u0434\u0435\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u044f\u0445, \u043a \u0441\u0442\u0430\u0440\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0435 \u0431\u044b\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 &#171;\u0432\u043e\u0434\u0430&#187; \u043f\u0440\u043e \u043a\u043b\u0438\u043a\u0435\u0440 &#8212; \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<br \/>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u043c\u0443 \u043d\u0435 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430 &#171;\u0432\u043e\u0434\u0430&#187;, \u043b\u0443\u0447\u0448\u0435 \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0430 [<a href=\"https:\/\/WebTransport-aioquic\" rel=\"noopener noreferrer nofollow\">\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 WebTransport \u0432 Python \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f aioquic<\/a>].<\/p>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u0441\u0435\u0442\u0438, \u043f\u0440\u0438 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 (\u0431\u0443\u0434\u044c \u0442\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438\u043b\u0438 web-\u0441\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a), \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f &#171;\u043a\u043b\u0438\u043a\u0435\u0440&#187;. \u0421\u0443\u0442\u044c \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0441\u0442\u0430 &#8212; \u0447\u0438\u0442\u0430\u044e\u0449\u0435\u043c\u0443 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0443 \u0441 \u043e\u0434\u043d\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439, \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u043a\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443. \u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b. \u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e. \u042f \u0431\u044b \u0434\u0430\u0436\u0435 \u043c\u043e\u0433 \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043a\u0443\u0447\u043d\u044b\u043c\u0438, \u0435\u0441\u043b\u0438 \u0431\u044b \u043d\u0438 \u043d\u0435\u0434\u0430\u0432\u043d\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 \u0425\u043e\u043c\u044f\u043a\u043e\u043c (Hamster Combat). \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u0443 \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0435\u0441\u0442\u044c \u0432\u043e\u043f\u043b\u043e\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0445.<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u043d\u0435 \u043c\u0430\u043b\u043e \u043b\u044e\u0434\u0435\u0439, \u0443\u0432\u0438\u0434\u0435\u0432 \u0442\u0430\u043a\u043e\u0439 \u0443\u0441\u043f\u0435\u0445 \u043a\u0430\u043a \u0443 \u0425\u043e\u043c\u044f\u043a\u0430, \u043f\u043e\u0431\u0435\u0436\u0430\u043b\u0438 \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0435\u0435. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u0438\u043c\u0447\u0438\u0432\u044b\u0435 \u043f\u043e\u0431\u0435\u0436\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u0438\u0442\u0438\u0440\u0443\u044e \u043a\u043b\u0438\u043a\u0438 (\u0442.\u0435. \u043f\u043e\u0448\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u043b\u043e\u043f\u0430\u0442\u044b). \u041d\u043e \u0434\u0430\u043b\u0435\u0435 \u043f\u043e\u0432\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0432\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u043b\u044e\u0434\u0435\u0439, \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u0435\u043b\u0435\u043c \u0434\u0430\u043d\u043d\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0431\u0443\u0434\u0435\u0442 John Doe, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c &#171;\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0443\u0441\u043f\u0435\u0445&#187;.<\/p>\n<blockquote>\n<p>(\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043f\u0440\u043e\u00a0\u043a\u043b\u0438\u043a\u0435\u0440 \u043d\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u0430\u044f \u0438\u00a0\u0431\u044b\u043b\u0430 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043d\u0430 \u043a\u0430\u043a \u00ab\u0432\u043e\u0434\u0430\u00bb \u043a\u00a0\u0437\u0430\u043c\u0435\u0442\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f\u00a0\u0431\u044b\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0440\u0430\u043d\u0435\u0435, \u043f\u0440\u0438\u00a0\u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0435 \u0441\u00a0\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 aioquic).<\/p>\n<\/blockquote>\n<h3>\u041f\u0440\u0438\u0447\u0435\u043c \u0442\u0443\u0442 WebTransport \u0438 HTTP\/3?<\/h3>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0433 \u0431\u044b\u0441\u0442\u0440\u043e \u043a\u043b\u0438\u043a\u0430\u0442\u044c \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0435, \u0430 \u0435\u0433\u043e \u0441\u0447\u0435\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u043b\u0441\u044f \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u043d\u0430\u0436\u0430\u0442\u0438\u0439 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443, \u0430 \u0442\u0430\u043a\u0436\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0431\u044b\u043b\u043e \u043b\u0438\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0430\u043d\u0438\u0439 (\u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439), \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0434\u0443\u043c\u0430\u0442\u044c\u0441\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c.<\/p>\n<blockquote>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0443\u0442\u043e\u0447\u043d\u0438\u043c, \u0447\u0442\u043e \u043f\u043e\u043a\u0430 \u043c\u044b \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043d\u0430\u0438\u0432\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0\u2014 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443.<\/p>\n<\/blockquote>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435, \u043e \u0447\u0435\u043c \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f \u043d\u0430\u0448 John Doe, \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u0437\u044b\u0432\u0447\u0438\u0432\u043e\u0433\u043e \u043a\u043b\u0438\u043a\u0435\u0440\u0430, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u0442\u044b\u0441\u044f\u0447\u0430\u043c \u0447\u0435\u043b\u043e\u0432\u0435\u043a \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u00a0\u2014 \u044d\u0442\u043e \u0432\u044b\u0431\u043e\u0440 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0435\u0439 \u043a\u043b\u0438\u043a\u0435\u0440\u0430:<\/p>\n<ul>\n<li>\n<p><strong>REST API \u043d\u0430 \u0431\u0430\u0437\u0435 HTTP\/1.1<\/strong> &#8212; &#171;\u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e&#187; &#8212; \u043f\u043e\u0434\u0443\u043c\u0430\u043b John Doe. \u041e\u0434\u0438\u043d \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043b\u044f PUT \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443. \u0418 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043b\u044f GET \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041e\u0434\u043d\u0430\u043a\u043e, \u0442\u0435, \u043a\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0437\u0443 \u0431\u0440\u043e\u0441\u0438\u043b\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434, \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c (\u0438\u043b\u0438 \u043d\u0430\u0433\u0443\u0433\u043b\u0438\u0442\u044c \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435) \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u0442\u0430\u043a\u043e\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043b\u0438\u0448\u043d\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0439, \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 TLS \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0438 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Head-of-line_blocking\" rel=\"noopener noreferrer nofollow\">Head-of-Line Blocking<\/a>). \u042d\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c-\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043a \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u043a \u043a\u043b\u0438\u043a\u0435\u0440\u0443 [\u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043d\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u043e\u0435 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0435\u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u043e].<\/p>\n<\/li>\n<li>\n<p><strong>WebSocket<\/strong> &#8212; &#171;\u0412\u043e\u0442 \u044d\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442&#187; &#8212; \u043f\u043e\u0434\u0443\u043c\u0430\u043b \u043d\u0430\u0448 John Doe, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0443\u0441\u043f\u0435\u043b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u0441 REST API \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u0440\u0443\u0442\u043e\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a <a href=\"https:\/\/fastapi.tiangolo.com\/\" rel=\"noopener noreferrer nofollow\">FastAPI<\/a> &#8212; &#171;\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u0432\u0435\u0434\u044c FastApi \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 WebSocket&#187;. WebSocket &#8212; \u044d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u0430\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c, \u043d\u043e \u043d\u0430\u0448 John Doe \u0443\u0441\u043f\u0435\u043b \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0438 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u043c\u0438 \u0442\u0438\u043f\u0430 &#171;&#8230; \u043d\u0430 \u0434\u0432\u043e\u0440\u0435 2024 \u0433\u043e\u0434, \u0437\u0430\u0447\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0438\u0437 2011 \u0433\u043e\u0434\u0430?&#187;. &#171;\u0418 \u0447\u0442\u043e \u0442\u043e\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c?&#187; &#8212; \u0437\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c \u043d\u0430\u0448 John Doe. \u0415\u0441\u0442\u044c \u0435\u0449\u0435 Long Polling, Server Sent Events, \u0430 \u0442\u0430\u043a\u0436\u0435 WebTransport.<\/p>\n<\/li>\n<li>\n<p><strong>WebTransport<\/strong> &#8212; \u044d\u0442\u043e \u043d\u043e\u0432\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043d\u0430 \u043d\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435 HTTP\/3. WebSockets \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 TCP, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043c\u0435\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f TCP, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u043b\u0430\u044e\u0442 \u0435\u0433\u043e \u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043a \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430\u043c (\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0435\u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445). WebTransport \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u043a\u0430\u043a \u043d\u0435\u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f UDP-\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0438 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 <a href=\"https:\/\/chromestatus.com\/feature\/4854144902889472\" rel=\"noopener noreferrer nofollow\">ref<\/a>. &#171;\u041d\u0443\u0436\u043d\u043e \u0431\u0440\u0430\u0442\u044c&#187; &#8212; \u0432\u043e\u0441\u043a\u043b\u0438\u043a\u043d\u0443\u043b John Doe \u0438 \u043f\u043e\u0448\u0435\u043b \u0447\u0438\u0442\u0430\u0442\u044c, \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0442\u043e\u0440\u043e\u0435, \u043e \u0447\u0435\u043c \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f John Doe &#8212; \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430. \u042d\u0442\u043e \u0442\u0435\u043c\u0430 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438, \u0433\u0434\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043b\u043e\u0436\u0435\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440 \u0441\u0438\u0441\u0442\u0435\u043c \u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u0432(\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432) \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d \u043f\u0440\u0438\u043d\u0446\u0438\u043f CQRS, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u044f \u0438 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b. \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0435 Pub\/Sub. \u0418\u043b\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043e \u0431\u0440\u043e\u043a\u0435\u0440\u0430\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 socket.  \u0418 \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435\u043c \u043a\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0430 \u043e\u0434\u043d\u0430 \u0438 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0425\u043e\u0442\u044f \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 (\u043a\u043b\u0438\u043a\u0435\u0440) \u043c\u043d\u043e\u0433\u0438\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0438 \u043a \u0447\u0435\u043c\u0443.<\/p>\n<h2>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 WebTransport \u0432 Python \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f aioquic<\/h2>\n<blockquote>\n<p>\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0442\u043e\u0438\u0442 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044c, \u0447\u0442\u043e <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/draft-ietf-webtrans-http3\" rel=\"noopener noreferrer nofollow\">WebTransport<\/a> \u0435\u0449\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0447\u0435\u0440\u043d\u043e\u0432\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435.<\/p>\n<\/blockquote>\n<p><a class=\"anchor\" name=\"WebTransport-aioquic\" id=\"WebTransport-aioquic\"><\/a><\/p>\n<p>WebTransport &#8212; \u044d\u0442\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/draft-ietf-webtrans-overview-07\" rel=\"noopener noreferrer nofollow\">ref<\/a> \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c, \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0438 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b HTTP\/3. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e WebTransport \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043f\u043e\u0432\u0435\u0440\u0445 HTTP\/3, \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0435\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0442\u043e\u043a\u0438 QUIC, \u0430 HTTP \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f &#171;\u0441\u0432\u043e\u0435\u0433\u043e \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u044f&#187;.<\/p>\n<p>\u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0435 \u0441 HTTP\/3 \u0438 QUIC \u044f \u043e\u0447\u0435\u043d\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/08\/http3-core-concepts-part1\/\" rel=\"noopener noreferrer nofollow\"><strong>Part 1: HTTP\/3 History And Core Concepts<\/strong><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/08\/http3-performance-improvements-part2\/\" rel=\"noopener noreferrer nofollow\"><strong>Part 2: HTTP\/3 Performance Features<\/strong><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/09\/http3-practical-deployment-options-part3\/\" rel=\"noopener noreferrer nofollow\"><strong>Part 3: Practical HTTP\/3 Deployment Options<\/strong><\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 QUIC \u0438 HTTP\/3 \u043d\u0430 python \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <a href=\"https:\/\/aioquic.readthedocs.io\/en\/latest\/\" rel=\"noopener noreferrer nofollow\">aioquic<\/a>. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c async\/await \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u0438 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c asyncio. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0432\u0435\u0431 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 (\u043a\u0430\u043a \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 FastApi), \u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u0430\u0447\u0430\u0442\u044c \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0441 <a href=\"https:\/\/aioquic.readthedocs.io\/en\/latest\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0442\u043e\u0440\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u043a\u043e\u0434\u0430 \u0438\u0437 GoooleChrome GitHub <a href=\"https:\/\/github.com\/GoogleChrome\/samples\/tree\/gh-pages\/webtransport\" rel=\"noopener noreferrer nofollow\">GoogleChrome\/samples\/webtransport<\/a><\/p>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0442 GoooleChrome \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 Python \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c JavaScript. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 &#8212; \u044d\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0448\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0447\u0442\u0438 \u043d\u0430\u0448\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441 \u043a\u043b\u0438\u043a\u0435\u0440\u043e\u043c. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0432 \u043d\u0435\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f, \u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 &#171;\u043f\u043e\u0447\u0442\u0438&#187;.<\/p>\n<h3>\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u043e\u0442 GoooleChrome<\/h3>\n<p>\u041a\u043e\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043e\u0442 GoooleChrome<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043e\u0442 GoooleChrome<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">  # ref: https:\/\/github.com\/GoogleChrome\/samples\/tree\/gh-pages\/webtransport  import argparse import asyncio import logging from collections import defaultdict from typing import Dict, Optional  from aioquic.asyncio import QuicConnectionProtocol, serve from aioquic.h3.connection import H3_ALPN, H3Connection from aioquic.h3.events import H3Event, HeadersReceived, WebTransportStreamDataReceived, DatagramReceived from aioquic.quic.configuration import QuicConfiguration from aioquic.quic.connection import stream_is_unidirectional from aioquic.quic.events import ProtocolNegotiated, StreamReset, QuicEvent  BIND_ADDRESS = '::1' BIND_PORT = 4433  logger = logging.getLogger(__name__)  class CounterHandler:      def __init__(self, session_id, http: H3Connection) -&gt; None:         self._session_id = session_id         self._http = http         self._counters = defaultdict(int)      def h3_event_received(self, event: H3Event) -&gt; None:         if isinstance(event, DatagramReceived):             payload = str(len(event.data)).encode('ascii')             self._http.send_datagram(self._session_id, payload)          if isinstance(event, WebTransportStreamDataReceived):             self._counters[event.stream_id] += len(event.data)             if event.stream_ended:                 if stream_is_unidirectional(event.stream_id):                     response_id = self._http.create_webtransport_stream(                         self._session_id, is_unidirectional=True)                 else:                     response_id = event.stream_id                 payload = str(self._counters[event.stream_id]).encode('ascii')                 self._http._quic.send_stream_data(                     response_id, payload, end_stream=True)                 self.stream_closed(event.stream_id)      def stream_closed(self, stream_id: int) -&gt; None:         try:             del self._counters[stream_id]         except KeyError:             pass   class WebTransportProtocol(QuicConnectionProtocol):      def __init__(self, *args, **kwargs) -&gt; None:         super().__init__(*args, **kwargs)         self._http: Optional[H3Connection] = None         self._handler: Optional[CounterHandler] = None      def quic_event_received(self, event: QuicEvent) -&gt; None:         if isinstance(event, ProtocolNegotiated):             self._http = H3Connection(self._quic, enable_webtransport=True)         elif isinstance(event, StreamReset) and self._handler is not None:             self._handler.stream_closed(event.stream_id)          if self._http is not None:             for h3_event in self._http.handle_event(event):                 self._h3_event_received(h3_event)      def _h3_event_received(self, event: H3Event) -&gt; None:         if isinstance(event, HeadersReceived):             headers = {}             for header, value in event.headers:                 headers[header] = value             if (headers.get(b\":method\") == b\"CONNECT\" and                     headers.get(b\":protocol\") == b\"webtransport\"):                 self._handshake_webtransport(event.stream_id, headers)             else:                 self._send_response(event.stream_id, 400, end_stream=True)          if self._handler:             self._handler.h3_event_received(event)      def _handshake_webtransport(self,                                 stream_id: int,                                 request_headers: Dict[bytes, bytes]) -&gt; None:         authority = request_headers.get(b\":authority\")         path = request_headers.get(b\":path\")         if authority is None or path is None:             self._send_response(stream_id, 400, end_stream=True)             return         if path == b\"\/counter\":             assert(self._handler is None)             self._handler = CounterHandler(stream_id, self._http)             self._send_response(stream_id, 200)         else:             self._send_response(stream_id, 404, end_stream=True)      def _send_response(self,                        stream_id: int,                        status_code: int,                        end_stream=False) -&gt; None:         headers = [(b\":status\", str(status_code).encode())]         if status_code == 200:             headers.append((b\"sec-webtransport-http3-draft\", b\"draft02\"))         self._http.send_headers(             stream_id=stream_id, headers=headers, end_stream=end_stream)   if __name__ == '__main__':     parser = argparse.ArgumentParser()     parser.add_argument('certificate')     parser.add_argument('key')     args = parser.parse_args()      configuration = QuicConfiguration(         alpn_protocols=H3_ALPN,         is_client=False,         max_datagram_frame_size=65536,     )     configuration.load_cert_chain(args.certificate, args.key)      loop = asyncio.get_event_loop()     loop.run_until_complete(         serve(             BIND_ADDRESS,             BIND_PORT,             configuration=configuration,             create_protocol=WebTransportProtocol,         ))     try:         logging.info(             \"Listening on https:\/\/{}:{}\".format(BIND_ADDRESS, BIND_PORT))         loop.run_forever()     except KeyboardInterrupt:         pass <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 <code>aioquic.asyncio.server()<\/code>:<\/p>\n<pre><code class=\"python\"># ... from aioquic.asyncio import QuicConnectionProtocol, serve # ... if __name__ == '__main__': # ... configuration = QuicConfiguration(         alpn_protocols=H3_ALPN,         is_client=False,         max_datagram_frame_size=65536,     )     # ... loop = asyncio.get_event_loop()     loop.run_until_complete(         serve(             BIND_ADDRESS,             BIND_PORT,             configuration=configuration,             create_protocol=WebTransportProtocol,         )) # ... # ...<\/code><\/pre>\n<p>\u0412\u044b\u0437\u043e\u0432 <strong>aioquic.asyncio.server<\/strong> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>aioquic.asyncio.server.QuicServer<\/code> \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0439 \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u0430\u0434\u0440\u0435\u0441\u0435 \u0438 \u043f\u043e\u0440\u0442\u0443. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0443\u0434\u0430 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0432 \u0435\u0433\u043e \u043e\u0442 <code>aioquic.asyncio.server.QuicServer<\/code>.<br \/> \u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>aioquic.asyncio.server()<\/code>, \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c <code>aioquic.quic.configuration.QuicConfiguration<\/code> \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 TLS \u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0438 \u043a\u043b\u0430\u0441\u0441 \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 <code>~asyncio.DatagramProtocol<\/code> \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435\u043c).<\/p>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u043e: <em>\u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <\/em><code>aioquic.quic.configuration.QuicConfiguration<\/code> \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043b\u043e\u0433\u0433\u0435\u0440\u0430 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043e\u0442 <code>aioquic.quic.logger.QuicLogger<\/code>, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0443\u0434\u043e\u0431\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 (\u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435).<\/p>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0442 GoooleChrome \u043e\u043f\u0438\u0441\u0430\u043d \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 <strong>WebTransportProtocol<\/strong> \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435\u043c:<\/p>\n<pre><code class=\"python\"># ... from aioquic.asyncio import QuicConnectionProtocol, serve from aioquic.h3.connection import H3_ALPN, H3Connection # ... class WebTransportProtocol(QuicConnectionProtocol):      def __init__(self, *args, **kwargs) -&gt; None:         super().__init__(*args, **kwargs)         self._http: Optional[H3Connection] = None         self._handler: Optional[CounterHandler] = None # ... # ...<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u0432\u044b \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 <code>~asyncio.DatagramProtocol<\/code> \u0438\u043b\u0438 <code>~asyncio.Protocol<\/code>, \u0442\u043e \u0432\u0430\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u0430 \u043f\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044e \u0442\u0430\u043a\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043a\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>connection_made(transport): \u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e. transport &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0430\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435\/\u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p>data_received(data) \u0438\u043b\u0438 datagram_received(data, addr): \u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0435\/\u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. data &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0430 addr &#8212; \u044d\u0442\u043e \u0430\u0434\u0440\u0435\u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0430 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0430.<\/p>\n<\/li>\n<li>\n<p>connection_lost(exc): \u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0437\u0430\u043a\u0440\u044b\u0442\u043e. exc &#8212; \u044d\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f. \u041e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>WebTransportProtocol<\/code> \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 <code>aioquic.asyncio.QuicConnectionProtocol<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 <code>asyncio.DatagramProtocol<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 aioquic \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e \u0432 \u0432\u0438\u0434\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC \u0438 HTTP\/3. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430 <code>WebTransportProtocol<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u0442\u0438\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c.<\/p>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC \u0432 aioquic<\/h3>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 <code>aioquic.asyncio.QuicConnectionProtocol<\/code> \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043c\u0435\u0442\u043e\u0434 <code>quic_event_received()<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f QUIC. \u0412 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0432 \u043f\u043e\u0434\u043a\u043b\u0430\u0441\u0441\u0435 WebTransportProtocol:<\/p>\n<pre><code class=\"python\"># ... from aioquic.h3.connection import H3_ALPN, H3Connection from aioquic.quic.events import ProtocolNegotiated, StreamReset, QuicEvent # ... class WebTransportProtocol(QuicConnectionProtocol): # ... def quic_event_received(self, event: QuicEvent) -&gt; None:         if isinstance(event, ProtocolNegotiated):             self._http = H3Connection(self._quic, enable_webtransport=True)         elif isinstance(event, StreamReset) and self._handler is not None:             self._handler.stream_closed(event.stream_id)          if self._http is not None:             for h3_event in self._http.handle_event(event):                 self._h3_event_received(h3_event) <\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>quic_event_received()<\/code> \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u0441\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>aioquic.quic.events.QuicEvent<\/code> \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u043e \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>aioquic.quic.events.ProtocolNegotiated<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u044f ALPN (Application-Layer Protocol Negotiation). \u0412 \u043a\u043e\u0434\u0435(\u043f\u0440\u0438\u043c\u0435\u0440\u0435) \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>aioquic.h3.connection.H3Connection<\/code>, \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f:<\/p>\n<pre><code class=\"python\"># ... if isinstance(event, ProtocolNegotiated): self._http = H3Connection(self._quic, enable_webtransport=True) # ...<\/code><\/pre>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u0435 <code>aioquic.quic.events.ProtocolNegotiated<\/code> \u0431\u0443\u0434\u0435\u0442 \u0441\u0430\u043c\u044b\u043c \u043f\u0435\u0440\u0432\u044b\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c (\u0438\u0437 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0432 <code>aioquic.quic.events<\/code>), \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0435 \u043f\u0440\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u043a \u0432\u0430\u0448\u0435\u043c\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>aioquic.quic.events.StreamReset<\/code>, \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0442\u043e\u043a:<\/p>\n<pre><code class=\"python\"># ... elif isinstance(event, StreamReset) and self._handler is not None: self._handler.stream_closed(event.stream_id) # ...<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 <code>quic_event_received()<\/code> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u0441\u043e\u0431\u044b\u0442\u0438\u044f QUIC \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 HTTP\/3 (\u043e \u043d\u0438\u0445 \u043c\u044b \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0434\u043d\u0435\u0435) \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 <code>self._h3_event_received()<\/code>:<\/p>\n<pre><code class=\"python\"># ... if isinstance(event, ProtocolNegotiated): self._http = H3Connection(self._quic, enable_webtransport=True) # ...<\/code><\/pre>\n<h4>\u0421\u043e\u0431\u044b\u0442\u0438\u044f QUIC \u0438\u0437 aioquic.quic.events<\/h4>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 aioquic \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC:<\/p>\n<ul>\n<li>\n<p><strong>ConnectionIdIssued<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e) \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440. \u041f\u043e \u0441\u0443\u0442\u0438, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f &#8212; \u044d\u0442\u043e \u043d\u0435\u043a\u0438\u0439 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440. \u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u043b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f. \u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043e\u0437\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>ConnectionIdRetired<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 <code>_retire_peer_cid()<\/code> \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0431\u044b\u043b \u043e\u0442\u043e\u0437\u0432\u0430\u043d \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d. \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u043e\u0432\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440. \u041e\u0431\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f ConnectionIdIssued \u0438 ConnectionIdRetired \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0438 [\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440] \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u044b\u0435(\u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0435) \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>ConnectionTerminated<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u044b\u0432\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f QUIC. \u0420\u0430\u0437\u0440\u044b\u0432 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c: \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u044f, \u0438\u043b\u0438 \u0435\u0441\u043b\u0438 \u0431\u044b\u043b\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0430 CONNECTION_CLOSE. \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438 \u0438 \u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>DatagramFrameReceived<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435. DatagramFrame &#8212; \u044d\u0442\u043e \u0435\u0434\u0438\u043d\u0438\u0446\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435 QUIC, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0436\u0434\u0443 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430\u043c\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>HandshakeCompleted<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f TLS \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f. \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043d\u0430\u043c, \u0447\u0442\u043e \u0434\u0430\u043b\u0435\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c, \u0432 \u0445\u043e\u0434\u0435 ALPN, \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u0431\u044b\u043b\u0438 \u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u044f (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 0-RTT \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0440\u0430\u0439\u043d\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u0434\u043d\u0430\u043a\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0432 \u0432\u043e\u043f\u0440\u043e\u0441\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438).<\/p>\n<\/li>\n<li>\n<p><strong>PingAcknowledged<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 ping \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435. \u0422.\u0435. \u043a\u043e\u0433\u0434\u0430 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0438\u043d\u0433, \u043e\u043d \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430. \u0415\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d, \u0442\u043e QUIC-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u0447\u0442\u043e \u0441\u0435\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e. \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 PING. \u0421\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e ping \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043b\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043c\u0435\u0442\u043e\u0434 <code>send_ping()<\/code> \u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 <code>QuicConnection<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>ProtocolNegotiated<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u044f ALPN \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>StopSendingReceived<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442, \u043a\u043e\u0433\u0434\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438 \u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u044b\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 (\u043d\u0435 \u043f\u0443\u0442\u0430\u0442\u044c \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f).<\/p>\n<\/li>\n<li>\n<p><strong>StreamDataReceived<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442, \u043a\u043e\u0433\u0434\u0430 \u0431\u044b\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435. \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u044b\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0444\u043b\u0430\u0433 \u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0438 FIN (\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u043f\u043e\u0442\u043e\u043a).<\/p>\n<\/li>\n<li>\n<p><strong>StreamReset<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442, \u043a\u043e\u0433\u0434\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0442\u043e\u043a. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430 \u0438 \u043a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 HTTP\/3 \u0432 aioquic<\/h3>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u0434\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC, aioquic \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u0430\u0442\u0430\u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0434\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 HTTP\/3. \u042d\u0442\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u043f\u043e\u0432\u0435\u0440\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC. \u0414\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC \u0438 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u043d\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0445\u0441\u044f \u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c HTTP\/3 \u0432 <code>aioquic.h3.connection.H3Connection<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043c\u0435\u0442\u043e\u0434 <code>handle_event()<\/code>. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u043c\u0435\u0442\u043e\u0434 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043e\u0434\u043d\u043e \u0438\u0437 \u0434\u0432\u0443\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC: <code>aioquic.quic.events.StreamDataReceived<\/code> \u0438 <code>aioquic.quic.events.DatagramFrameReceived<\/code>.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 HTTP\/3, \u0440\u0430\u043d\u0435\u0435, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>aioquic.h3.connection.H3Connection<\/code>:<\/p>\n<pre><code class=\"python\"># ... class WebTransportProtocol(QuicConnectionProtocol): # ... def quic_event_received(self, event: QuicEvent) -&gt; None:         if isinstance(event, ProtocolNegotiated): self._http = H3Connection(self._quic, enable_webtransport=True) # ...<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0430\u0445 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a HTTP\/3 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0432\u044b\u0437\u0432\u0430\u0432 \u043c\u0435\u0442\u043e\u0434 <code>handle_event()<\/code> \u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>aioquic.h3.connection.H3Connection<\/code>;<\/p>\n<pre><code class=\"python\"># ... class WebTransportProtocol(QuicConnectionProtocol): # ... def quic_event_received(self, event: QuicEvent) -&gt; None: # ... if self._http is not None: for h3_event in self._http.handle_event(event): self._h3_event_received(h3_event) # ...<\/code><\/pre>\n<h4>\u0421\u043e\u0431\u044b\u0442\u0438\u044f HTTP\/3 \u0438\u0437 aioquic.h3.events<\/h4>\n<ul>\n<li>\n<p><strong>HeadersReceived<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u041e\u043d\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u0432\u0438\u0434\u0435 \u043f\u0430\u0440 \u043a\u043b\u044e\u0447:\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041e\u0431\u044b\u0447\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043c\u0435\u0442\u043e\u0434\u0430 \u0438 \u0430\u0434\u0440\u0435\u0441\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 (\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438). \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442: \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430 \u0438 \u0444\u043b\u0430\u0433 \u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 FIN, \u0434\u043b\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430. \u0412 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0442 GoogleChrome \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u043a\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>_h3_event_received()<\/code> \u043a\u043b\u0430\u0441\u0441\u0430 WebTransportProtocol. \u0415\u0441\u043b\u0438 \u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u0440\u0430\u043d\u0435\u0435, \u043a\u043e\u0433\u0434\u0430 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f QUIC \u043c\u044b \u0437\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>aioquic.h3.connection.H3Connection<\/code>, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043f\u043e \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u0438 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430 \u043d\u0430\u0448\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0440\u0430\u0437\u043e\u0440\u0432\u0430\u043d\u043e. \u0412\u0441\u0435 \u0434\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u043b \u043d\u0430\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c\u0438 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u0432 \u043e\u0442\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. \u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043c\u0435\u0442\u043e\u0434 <code>_handshake_webtransport()<\/code> \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434 <code>_h3_event_received()<\/code>. \u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0414\u0430, \u0432\u0441\u0435 \u0442\u0430\u043a &#8212; \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u043b\u044f \u043d\u0438\u0445 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0444\u0440\u0435\u0439\u043c\u0430, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0438\u0445 \u0432 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u043a\u0435\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>DataReceived<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043a\u043e\u0433\u0434\u0430 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>DatagramReceived<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043a\u043e\u0433\u0434\u0430 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0430. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0442\u043e\u043a\u0430 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0430 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>WebTransportStreamDataReceived<\/strong> &#8212; \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043a\u043e\u0433\u0434\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c WebTransport \u043f\u043e\u0442\u043e\u043a\u0435 \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0411\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e QUIC \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 \u043e\u0447\u0435\u043d\u044c \u043a\u043b\u0430\u0441\u0441\u043d\u043e\u0439 (\u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434) \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/www.andy-pearce.com\/blog\/posts\/2023\/Mar\/http3-in-practice-quic\/\" rel=\"noopener noreferrer nofollow\">HTTP\/3 in Practice \u2014\u00a0QUIC<\/a><\/p>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0432 aioquic \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435<\/h3>\n<h4>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0430 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0439 QUIC \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 aioquic, \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0447\u0442\u043e \u0436\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435, \u043f\u0440\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 (\u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code>).<\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0431\u0443\u0434\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 (\u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435). \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u043d\u0430 javascript:<\/p>\n<pre><code class=\"javascript\">async function initTransport(url) {   const transport = new WebTransport(url);   await transport.ready;   return transport; }<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 WebTransport, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043b\u0438\u0448\u044c \u0430\u0434\u0440\u0435\u0441, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0431\u0435\u0437 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0445 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043e\u0432 \u0438 \u0441 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 Web PKI \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code> \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0432\u043d\u0435\u0441\u0435\u043c \u0432 \u043d\u0435\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0417\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u043a\u043e\u0434\u0430, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0443\u044e \u0437\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f H3Connection \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 WebTransport:<\/p>\n<pre><code class=\"python\"># ... class WebTransportProtocol(QuicConnectionProtocol): # ... def quic_event_received(self, event: QuicEvent) -&gt; None:         if isinstance(event, ProtocolNegotiated):         # \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 H3             # self._http = H3Connection(self._quic, enable_webtransport=True)         # ... # ...<\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0438, \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f \u043d\u0430\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0439:<\/p>\n<ol>\n<li>\n<p>ProtocolNegotiated &#8212; \u043a\u0430\u043a \u0438 \u0431\u044b\u043b\u043e \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e \u0440\u0430\u043d\u0435\u0435, \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435. \u0412 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d ProtocolNegotiated(alpn_protocol=&#8217;h3&#8242;)<\/p>\n<\/li>\n<li>\n<p>HandshakeCompleted &#8212; \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f TLS \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>StreamDataReceived &#8212; \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044e\u0449\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>ConnectionIdIssued &#8212; \u041f\u043e\u043b\u0443\u0447\u0438\u043c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0440\u0430\u043d\u0435\u0435 \u043c\u044b \u043d\u0435 \u0441\u0442\u0430\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c HTTP\/3 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 (\u0437\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u0441 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>aioquic.h3.connection.H3Connection<\/code>), \u0442\u043e \u043f\u043e \u043f\u0440\u043e\u0448\u0435\u0441\u0442\u0432\u0438\u0438 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f  <code>quic_event_received()<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>aioquic.quic.events.ConnectionTerminated<\/code> \u0438\u0437-\u0437\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u044f.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432\u0435\u0440\u043d\u0435\u043c \u0441\u0442\u0440\u043e\u0447\u043a\u0443 <code>self._http = H3Connection(self._quic, enable_webtransport=True)<\/code>, \u0442\u043e \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0435\u0449\u0435 \u0434\u0432\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>aioquic.quic.events.StreamDataReceived<\/code>.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u044b\u0439 (\u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438) \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u044f):<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/531\/3f9\/d9c\/5313f9d9cab68a885b36f2c68858206b.png\" width=\"479\" height=\"874\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/531\/3f9\/d9c\/5313f9d9cab68a885b36f2c68858206b.png\"\/><\/figure>\n<ul>\n<li>\n<p>Datagram 1<\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0443 (datagram 1) c \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u044e\u0449\u0438\u043c \u043f\u0430\u043a\u0435\u0442\u043e\u043c (packet #1 Initial), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 TLS &#171;ClientHello&#187;. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f: \u043d\u0430\u0431\u043e\u0440 \u0448\u0438\u0444\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442; \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043b\u044e\u0447; \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442; \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u043b \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043f\u0430\u043a\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0443 (datagram 1) \u0434\u043e \u0434\u043b\u0438\u043d\u044b 1200 \u0431\u0430\u0439\u0442. <\/p>\n<\/li>\n<li>\n<p>event = ProtocolNegotiated<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 ProtocolNegotiated \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b (datagram 1) \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. <\/p>\n<\/li>\n<li>\n<p>Datagram 2<\/p>\n<p>\u0412 \u043e\u0442\u0432\u0435\u0442 (datagram 2) \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 TLS &#171;ServerHello&#187;, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u0432 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u044e\u0449\u0438\u043c \u043f\u0430\u043a\u0435\u0442\u0435 (packet #0 Initial). \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f: \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430; \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0448\u0438\u0444\u0440\u043e\u0432; \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u043a\u043b\u044e\u0447; \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430. \u0412 \u044d\u0442\u043e\u0439 \u0436\u0435 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u043f\u0430\u043a\u0435\u0442 \u0441 &#171;\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435\u043c&#187; (packet #1 handshake), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432 \u0438 \u043f\u0435\u0440\u0435\u0447\u0435\u043d\u044c \u0432\u0441\u0435\u0445 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>Datagram 3<\/p>\n<p>\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0441 &#171;\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435\u043c&#187; (packet #2 handshake), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u044e\u0449\u0443\u044e \u044d\u0444\u0435\u043c\u0435\u0440\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0441 \u0437\u0430\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c. \u041a\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u043e\u0447\u0435\u043c\u0443 \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0438, \u0447\u0442\u043e &#171;\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435&#187; \u043f\u0440\u043e\u0448\u043b\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e (\u0445\u0435\u0448 \u0432\u0441\u0435\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u044f).<\/p>\n<\/li>\n<li>\n<p>event = HandshakeCompleted<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 HandshakeCompleted \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b (datagram 3) \u043a\u043b\u0438\u0435\u043d\u0442\u0443.<\/p>\n<\/li>\n<li>\n<p>Datagram 4<\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u043f\u0430\u043a\u0435\u0442\u0430 \u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 (Datagram 1 packet #1 Initial)<\/p>\n<\/li>\n<li>\n<p>Datagram 5<\/p>\n<p>\u0411\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0430\u043a\u0435\u0442\u0430 \u0441 &#171;\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435\u043c&#187;, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u043c TLS \u0437\u0430\u043f\u0438\u0441\u044c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u043d\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0432\u044f\u0437\u0438.<\/p>\n<\/li>\n<li>\n<p>Datagram 6<\/p>\n<p>\u041a\u0430\u043a\u0438\u0435-\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u0412\u044b\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0432 \u0440\u043e\u043b\u0438 PING \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f (\u043b\u0438\u0431\u043e \u044f \u043d\u0435 \u043f\u043e\u043d\u044f\u043b \u0437\u0430\u0447\u0435\u043c).<\/p>\n<\/li>\n<li>\n<p>event = StreamDataReceived<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 StreamDataReceived \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0435 (datagram 6).<\/p>\n<\/li>\n<li>\n<p>Datagram 7<\/p>\n<p>\u0421\u0435\u0440\u0432\u0435\u0440 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u043f\u0430\u043a\u0435\u0442 \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 &#171;\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u044f&#187;, \u0430 \u0442\u0430\u043a\u0436\u0435 PONG \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<li>\n<p>event = StreamDataReceived<\/p>\n<p>\u0421 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435. \u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 StreamDataReceived \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>Datagram 8<\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0435\u0441\u044f \u043a HTTP\/3.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0444\u0440\u0435\u0439\u043c\u0430), \u043d\u043e aioquic \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432.<\/p>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 WebTransport \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u0440\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f: \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0432 \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0432 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a.<\/p>\n<h4>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b<\/h4>\n<p>\u0414\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 javascript:<\/p>\n<pre><code class=\"javascript\">async function sendDatagram(transport, data) { let dWriter = transport.datagrams.writable.getWriter(); await dWriter.write(data); }<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u043d\u044b\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b (\u0434\u0432\u0435 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b):<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/18f\/55e\/a25\/18f55ea2571104b7a16bff2860590105.png\" width=\"508\" height=\"692\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/18f\/55e\/a25\/18f55ea2571104b7a16bff2860590105.png\"\/><\/figure>\n<ul>\n<li>\n<p>Datagram 1<\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0443 (datagram 1) c \u043f\u0430\u043a\u0435\u0442\u043e\u043c (packet #7 1RTT), \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 DatagramFrame.<\/p>\n<\/li>\n<li>\n<p>event = DatagramFrameReceived \u0438 h3_event = DatagramReceived<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 DatagramFrameReceived \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b (datagram 1) \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0434\u0430\u043b\u0435\u0435 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f QUIC \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>handle_event()<\/code> \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>aioquic.h3.connection.H3Connection<\/code>, \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 DatagramReceived.<\/p>\n<\/li>\n<li>\n<p>Datagram 2<\/p>\n<p>\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u0432\u0435\u0442\u0438\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u0439 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u043e\u0439 \u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f. \u041e\u0442\u0432\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c <code>CounterHandler<\/code> (\u043e \u043d\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0438\u0436\u0435).<\/p>\n<\/li>\n<\/ul>\n<h4>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0432 \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a<\/h4>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 javascript:<\/p>\n<pre><code class=\"javascript\">async function sendToUnidirectionalStream(transport, data) { let stream = await transport.createUnidirectionalStream();   let writer = stream.getWriter();   await writer.write(data);   await writer.close(); }<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u043d\u044b\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0432 \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f24\/231\/fd5\/f24231fd565f2fc0616e7964b31f7192.png\" width=\"508\" height=\"702\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f24\/231\/fd5\/f24231fd565f2fc0616e7964b31f7192.png\"\/><\/figure>\n<ul>\n<li>\n<p>Datagram 1<\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0438\u043c \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u0442\u043e\u043a\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p>event =StreamDataReceived<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>quic_event_received()<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 StreamDataReceived \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043f\u043e\u0442\u043e\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p>Datagram 3,4<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u043e\u0442\u043e\u043a \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d, \u043a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0447\u0430\u0442\u044c \u0432 \u043e\u0434\u043d\u043e\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443. \u0412 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u043e\u0434\u043d\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u043e\u0442\u043e\u043a, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0435\u0433\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435. \u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 3\u0439 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0435 (packet 8) \u0431\u044b\u043b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0431\u0438\u0442 FIN \u0432 \u043f\u043e\u0442\u043e\u043a\u0435. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0442\u043e\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u0430\u043a\u0440\u044b\u0442, \u0430 \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 \u043d\u043e\u0432\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p>Datagram 5<\/p>\n<p>\u041e\u0442\u0432\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c <code>CounterHandler<\/code>, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043a\u043b\u0438\u0435\u043d\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u043b \u0431\u0438\u0442 FIN.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0432 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a<\/h4>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 javascript:<\/p>\n<pre><code class=\"javascript\">async function sendToBidirectionalStream(transport, data) { let stream = await transport.createBidirectionalStream();   let writer = stream.getWriter();   await writer.write(data);   await writer.close();<\/code><\/pre>\n<p>\u0421\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u0445\u043e\u0436\u0438. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c <code>CounterHandler<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d \u0432 \u0442\u043e\u043c \u0436\u0435 (\u0441 \u0442\u0435\u043c \u0436\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c) \u043f\u043e\u0442\u043e\u043a\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>BidirectionalStream.png<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d7c\/755\/248\/d7c755248bf431f0ea75c741fe9f24d4.png\" width=\"508\" height=\"697\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d7c\/755\/248\/d7c755248bf431f0ea75c741fe9f24d4.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/h3>\n<p>\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0431\u0443\u0434\u0443\u0442 \u043d\u0435 \u043f\u043e\u043b\u043d\u044b\u043c\u0438, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044c \u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b \u043e\u0442\u0432\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u043d\u0430 \u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0442 GoogleChrome \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"python\"># ... from collections import defaultdict # ... from aioquic.h3.connection import H3Connection from aioquic.h3.events import H3Event, WebTransportStreamDataReceived, DatagramReceived from aioquic.quic.connection import stream_is_unidirectional # ... class CounterHandler:      def __init__(self, session_id, http: H3Connection) -&gt; None:         self._session_id = session_id         self._http = http         self._counters = defaultdict(int)      def h3_event_received(self, event: H3Event) -&gt; None:         # ...      def stream_closed(self, stream_id: int) -&gt; None:         # ... # ... <\/code><\/pre>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438 <code>aioquic.h3.events.H3Event<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 <code>h3_event_received()<\/code>.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043b\u0438\u0435\u043d\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0443, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>aioquic.h3.events.DatagramReceived<\/code>:<\/p>\n<pre><code class=\"python\"># ... def h3_event_received(self, event: H3Event) -&gt; None: if isinstance(event, DatagramReceived): payload = str(len(event.data)).encode('ascii') self._http.send_datagram(self._session_id, payload) # ... # ...<\/code><\/pre>\n<p>\u0411\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u0434\u043b\u0438\u043d\u044b \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u0430 <code>send_datagram()<\/code> \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 <code>aioquic.h3.connection.H3Connection<\/code>.<\/p>\n<p>\u041f\u0440\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0442\u043e\u043a, \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>aioquic.h3.events.WebTransportStreamDataReceived<\/code>:<\/p>\n<pre><code class=\"python\"># ... def h3_event_received(self, event: H3Event) -&gt; None: # ... if isinstance(event, WebTransportStreamDataReceived): self._counters[event.stream_id] += len(event.data) if event.stream_ended: if stream_is_unidirectional(event.stream_id): response_id = self._http.create_webtransport_stream( self._session_id, is_unidirectional=True) else: response_id = event.stream_id payload = str(self._counters[event.stream_id]).encode('ascii') self._http._quic.send_stream_data( response_id, payload, end_stream=True) self.stream_closed(event.stream_id) # ...<\/code><\/pre>\n<p>\u0418\u0437 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439, \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0434\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p><code>create_webtransport_stream()<\/code> &#8212; \u043c\u0435\u0442\u043e\u0434 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 <code>aioquic.h3.connection.H3Connection<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430. \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0443, \u0442\u0430\u043a \u043a\u0430\u043a \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u044b\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a.<\/p>\n<\/li>\n<li>\n<p><code>send_stream_data<\/code> &#8212; \u043c\u0435\u0442\u043e\u0434 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 <code>aioquic.quic.connection.QuicConnection<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 QUIC.<\/p>\n<\/li>\n<\/ul>\n<h2>\u041f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0439 &#171;\u043a\u043b\u0438\u043a\u0435\u0440&#187;<\/h2>\n<blockquote>\n<p>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435: \u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0440\u0430\u0437\u0434\u0435\u043b \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043a\u0430\u043a \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f (\u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e &#171;\u043a\u043b\u0438\u043a\u0435\u0440&#187;). \u0420\u0430\u0437\u0434\u0435\u043b \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0435\u0439 \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043a\u043b\u0438\u043a\u0435\u0440\u0430 \u0438\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c &#171;\u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u043f\u0440\u0430\u043a\u0442\u0438\u043a&#187;. \u041e\u0434\u043d\u0430\u043a\u043e, \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0445\u043e\u0447\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 &#171;\u043a\u043b\u0438\u043a\u0435\u0440&#187; \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0445 (\u0432\u0430\u0436\u043d\u044b\u0445) \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0438 \u043a\u0430\u043a \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f, \u0442\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u044d\u0442\u043e.<\/p>\n<\/blockquote>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0431\u044b\u043b\u043e \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 aioquic, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 &#8212; \u043a\u043b\u0438\u043a\u0435\u0440.<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u043b\u044f \u0441\u0447\u0435\u0442\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<pre><code class=\"python\">import itertools from collections import defaultdict  class SimpleScoreStore:       \"\"\" \u041f\u0440\u043e\u0441\u0442\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438\u0433\u0440\u043e\u043a\u043e\u0432 \u0438 \u0438\u0445 \u0441\u0447\u0435\u0442\u043e\u0432. (In-Memory) \"\"\"       def __init__(self) -&gt; None:           self.scores = defaultdict(itertools.count)          def inc_score(self, user: str) -&gt; int:           \"\"\" \u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0441\u0447\u0435\u0442 \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443 \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \"\"\"           return next(self.scores[user])  # \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441\u0447\u0435\u0442\u043e\u0432 \u0438\u0433\u0440\u043e\u043a\u043e\u0432.   simple_score_store = SimpleScoreStore() <\/code><\/pre>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0447\u0435\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0434\u0430\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0438\u043d\u043e\u0435.<\/p>\n<p>\u0414\u0440\u0443\u0433\u0438\u043c \u0432\u0430\u0436\u043d\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043c\u0435\u043d\u0430 <code>CounterHandler<\/code> \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u043d\u0430\u0448\u0435\u0433\u043e &#171;\u043a\u043b\u0438\u043a\u0435\u0440\u0430&#187;.<\/p>\n<details class=\"spoiler\">\n<summary>\u0437\u0430\u043c\u0435\u043d\u0430 CounterHandler \u043d\u0430 ClickerHandler<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">class ClickerHandler:     \"\"\"     \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u041a\u043b\u0438\u043a\u0435\u0440\u0430.     \"\"\"      def __init__(             self,             connection: h3_connection.H3Connection,             stream_id: int,     ) -&gt; None:         self.connection = connection         self.session_stream_id = stream_id      def create_wt_unidirectional_stream(self) -&gt; int:         \"\"\"         \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a WebTransport.         :return: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430.         \"\"\"         return self.connection.create_webtransport_stream(             session_id=self.session_stream_id, is_unidirectional=True         )      def send_stream_data(             self,             stream_id: int,             data: bytes,             end_stream: bool = False     ) -&gt; None:         \"\"\"         \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a.          :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435.         :param data: \u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438.         :param end_stream: \u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u043f\u043e\u0442\u043e\u043a.         \"\"\"         self.connection._quic.send_stream_data(             stream_id=stream_id,             data=data,             end_stream=end_stream,         )      def send_datagram(self, data: bytes, stream_id: int | None = None) -&gt; None:         \"\"\"         \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b (DatagramFrame).         :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430, \u043a\u0443\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435.         :param data: \u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438.         \"\"\"         if stream_id is None:             stream_id = self.session_stream_id         self.connection.send_datagram(stream_id, data=data)      def stop_stream(self, stream_id: int, code: int) -&gt; None:         \"\"\"         \u041e\u0442\u043f\u0440\u0430\u0432\u044c\u0442\u0435 DatagramFrame \u0441 STOP_SENDING \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a.         :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c.         :param code: \u041a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438.         \"\"\"         self.connection._quic.stop_stream(stream_id, code)      def reset_stream(self, stream_id: int, code: int) -&gt; None:         \"\"\"         \u041e\u0442\u043f\u0440\u0430\u0432\u044c\u0442\u0435 DatagramFrame \u0441 RESET_STREAM \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a.         :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c.         :param code: the reason of the error.         \"\"\"         self.connection._quic.reset_stream(stream_id, code)      def h3_event_received(self, event: h3_events.H3Event):         \"\"\"         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 HTTP\/3.                  :param event: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u044f HTTP\/3.         \"\"\"         if isinstance(event, h3_events.DatagramReceived):             self._datagram_received(event.data)          elif isinstance(event, h3_events.WebTransportStreamDataReceived):             self._stream_data_received(event.stream_id, event.data, event.stream_ended)      def _stream_data_received(self, stream_id: int, data: bytes, stream_ended: bool):         \"\"\"         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 WebTransport.          :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435.         :param data: \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.         :param stream_ended: \u0411\u044b\u043b \u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0431\u0438\u0442 FIN \u0432 \u043a\u0430\u0434\u0440\u0435 STREAM.         \"\"\"         res = self.payload_to_score(data)         if quic_connection.stream_is_unidirectional(stream_id):             response_stream_id = self.create_wt_unidirectional_stream()         else:             response_stream_id = stream_id         if res is not None:             res = json.dumps({\"status\": 200, \"score\": res}).encode('utf-8')         else:             res = json.dumps({\"status\": 400}).encode('utf-8')         self.send_stream_data(response_stream_id, res, end_stream=False)         if stream_ended:             self._stream_closed(stream_id)      def _datagram_received(self, data: bytes):         \"\"\"         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0432 \u0441\u0435\u0430\u043d\u0441\u0435 WebTransport \u0438\u0437 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b.          :param data: \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.         \"\"\"         res = self.payload_to_score(data)         if res is not None:             self.send_datagram(json.dumps({\"status\": 200, \"score\": res}).encode('utf-8'))         else:             self.send_datagram(json.dumps({\"status\": 400}).encode('utf-8'))      @staticmethod     def payload_to_score(data: bytes) -&gt; int | None:         \"\"\"         \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0447\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.          :param data: \u0414\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443.         :return: \u0421\u0447\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.         \"\"\"         res = None         data: dict = json.loads(data.decode('utf-8')) if len(data) &gt; 0 else {}         username = data.get('username')         type_ = data.get('type')         if type_ == 'increment':             if username:                 res = simple_score_store.inc_score(username)         return res      def _stream_closed(self, stream_id: int):         \"\"\"         \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u043f\u043e\u0442\u043e\u043a\u0430 WebTransport.          :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430.         \"\"\"         self.send_stream_data(stream_id, b'', end_stream=True)      def stream_reset(             self,             stream_id: int,             error_code: int     ) -&gt; None:         \"\"\"         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435, \u043a\u043e\u0433\u0434\u0430 \u0423\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u043b \u0441\u0431\u0440\u043e\u0441 \u043f\u043e\u0442\u043e\u043a\u0430.          :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430.         :param error_code: \u041a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438.         \"\"\"         pass <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0434\u0432\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f: <code>aioquic.h3.events.DatagramReceived<\/code> \u0438 <code>aioquic.h3.events.WebTransportStreamDataReceived<\/code> \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 \u0432\u0438\u0434\u0435 \u0444\u0440\u0435\u0439\u043c\u0430 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0438 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 <code>_datagram_received()<\/code> \u0438 <code>_stream_data_received()<\/code>.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 <code>WebTransportProtocol<\/code> \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438 \u0441\u0443\u0442\u044c \u0435\u0433\u043e \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0442\u043e\u0439 \u0436\u0435 &#8212; \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c &#171;\u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435 \u0434\u043b\u044f WebTransport&#187; \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 <code>ClickerHandler<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043b\u0430\u0441\u0441 WebTransportProtocol<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">class WebTransportProtocol(aio_protocol.QuicConnectionProtocol):     \"\"\"     WebTransportProtocol \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f WebTransport \u0438     \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443.     \"\"\"      def __init__(self, *args, **kwargs):         super().__init__(*args, **kwargs)         self._http: h3_connection.H3Connection | None = None         self._handler: ClickerHandler | None = None      def quic_event_received(self, event: quic_events.QuicEvent):         if isinstance(event, quic_events.ProtocolNegotiated):             if event.alpn_protocol == \"h3\":                 self._http = h3_connection.H3Connection(                     self._quic,                     enable_webtransport=True,                 )         elif isinstance(event, quic_events.StreamReset) and self._handler is not None:             self._handler.stream_reset(event.stream_id, event.error_code)          if self._http is not None:             for h3_event in self._http.handle_event(event):                 self.h3_event_received(h3_event)      def h3_event_received(self, event: h3_events.H3Event):         \"\"\"         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 HTTP\/3.         \"\"\"         if isinstance(event, h3_events.HeadersReceived):             headers = {}             for header, value in event.headers:                 headers[header] = value              if headers.get(b\":method\") == b\"CONNECT\":                 self.connect_received(event.stream_id, headers)             else:                 self._send_headers(event.stream_id, status_code=404, end_stream=True)          if self._handler is not None:             self._handler.h3_event_received(event)      def connect_received(self, stream_id: int, request_headers: dict[bytes, bytes]):         \"\"\"         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a\u043e\u0433\u0434\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c CONNECT.          :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430.         :param request_headers: \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u043e\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0443\u0437\u043b\u0430.         \"\"\"         if request_headers.get(b\":protocol\") == b\"webtransport\":             authority = request_headers.get(b\":authority\")             path = request_headers.get(b\":path\")             self._handshake_wt(stream_id, authority, path)         else:             self._send_headers(                 stream_id, status_code=404, end_stream=True,                 details=b\"Unsupported protocol.\",             )      def _handshake_wt(self, stream_id: int, authority: bytes | None, path: bytes | None, ):         \"\"\"         \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a\u043e\u0433\u0434\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0443\u0437\u0435\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u043b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 WebTransport.         :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430.         :param authority: \u0412 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 HTTP\/3, \"authority\" \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u043d\u0438 \u0445\u043e\u0441\u0442\u0430 \u0438\u043b\u0438 \u0434\u043e\u043c\u0435\u043d\u0430.         :param path: \u041f\u0443\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u043b\u044f WebTransport.         \"\"\"         if self._http is None:             self._send_headers(                 stream_id, status_code=500, end_stream=True,                 details=b\"H3Connection not created.\",             )         if authority is None or path is None:             self._send_headers(                 stream_id, status_code=400, end_stream=True,                 details=b\":authority` and `:path` must be provided.\",             )         elif path == b\"\/clicker\":             self._handler = ClickerHandler(connection=self._http, stream_id=stream_id)             self._send_headers(stream_id, status_code=200)         else:             self._send_headers(stream_id, status_code=404, details=b\"Path not found.\", end_stream=True)      def _send_headers(             self,             stream_id: int,             status_code: int,             details: bytes | None = None,             end_stream=False     ):         \"\"\"         \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 HTTP\/3.         :param stream_id: \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e\u0442\u043e\u043a\u0430.         :param status_code: \u041a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438.         :param end_stream: \u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a.         \"\"\"         headers = [(b\":status\", str(status_code).encode())]         if details is not None:             headers.append((b\"details\", details))         if status_code == 200:             headers.append((b\"sec-webtransport-http3-draft\", b\"draft02\"))         self._http.send_headers(             stream_id=stream_id, headers=headers, end_stream=end_stream         ) <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e:<\/p>\n<pre><code class=\"python\">class ServerStatus(enum.Enum):     \"\"\" \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \"\"\"     # \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430     WAITING_TO_START = 1     # \u0437\u0430\u043f\u0443\u0449\u0435\u043d     RUNNING = 2     # \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d     STOPPED = 3   class ClickerServer:     \"\"\" \u0421\u0435\u0440\u0432\u0435\u0440 \u043a\u043b\u0438\u043a\u0435\u0440\u0430. \"\"\"      def __init__(             self,             host: str,             port: int,             certfile: os.PathLike,             keyfile: os.PathLike | None = None,             password: bytes | str | None = None,     ):         self._thread: threading.Thread | None = None         self._host = host         self._port = port         self._configuration = quic_configuration.QuicConfiguration(             alpn_protocols=h3_connection.H3_ALPN,             is_client=False,             max_datagram_frame_size=65536,         )         self._configuration.load_cert_chain(             certfile=certfile,             keyfile=keyfile,             password=password,         )         self._status = ServerStatus.WAITING_TO_START         self._loop: asyncio.AbstractEventLoop | None = None      def run(self, non_blocking_mode: bool = False):         \"\"\"         \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440, \u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0449\u0435 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d.         :param non_blocking_mode: \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0435\u043c \u0440\u0435\u0436\u0438\u043c\u0435.         \"\"\"         if self._status == ServerStatus.RUNNING:             return         if non_blocking_mode:             self._thread = threading.Thread(                 target=self._run_until_stopped,                 daemon=True,             )             self._thread.start()         else:             self._run_until_stopped()      def stop(self):         \"\"\"         \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440.          \u0411\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0446\u0438\u043a\u043b \u0441\u043e\u0431\u044b\u0442\u0438\u0439,         \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0439 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u043e\u0440\u0435\u0435.         \"\"\"         if self._status == ServerStatus.RUNNING:             if self._loop:                 if self._thread:                     self._loop.call_soon_threadsafe(self._loop.stop)                     self._thread.join(timeout=15.0)                     if self._thread.is_alive():                         raise RuntimeError(                             \"\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0437\u0430 15 \u0441\u0435\u043a\u0443\u043d\u0434. \"                             \"\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043e\u043d \u0437\u0430\u0432\u0438\u0441.\"                         )                 else:                     self._loop.stop()         self._status = ServerStatus.STOPPED         self._thread = None         self._loop = None      def _run_until_stopped(self):         self._status = ServerStatus.RUNNING         if self._loop is None:             self._loop = asyncio.new_event_loop()         self._loop.run_until_complete(             serve(                 host=self._host,                 port=self._port,                 configuration=self._configuration,                 create_protocol=WebTransportProtocol             )         )         self._loop.run_forever()      def status(self) -&gt; ServerStatus:         \"\"\"         \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u0442\u0430\u0442\u0443\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.         :return: \u0421\u0442\u0430\u0442\u0443\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.         \"\"\"         return self._status   if __name__ == '__main__':     cert_file = pathlib.Path(os.path.join(os.path.dirname(__file__), 'certificate.pem'))     key_for_cert_file = pathlib.Path(os.path.join(os.path.dirname(__file__), 'certificate.key'))     if not cert_file.exists() or not key_for_cert_file.exists():         raise RuntimeError(\"\u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0444\u0430\u0439\u043b \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u0438 \u043a\u043b\u044e\u0447\u0430.\")     server = ClickerServer(         host='::1',         port=4433,         certfile=cert_file,         keyfile=key_for_cert_file,     )     try:         server.run()     except KeyboardInterrupt:         server.stop()  <\/code><\/pre>\n<details class=\"spoiler\">\n<summary>clocker.js<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">let currentTransport; \/\/ \u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442. let streamNumber; \/\/ \u041d\u043e\u043c\u0435\u0440 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430. let currentTransportDatagramWriter; \/\/ \u0414\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c. let currentBiStream; \/\/ \u0422\u0435\u043a\u0443\u0449\u0438\u0439 (\u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439) \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a\u0430. let readableBiStream; let writableBiStream; let biStreamWriter; \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a. let username; \/\/ \u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. let currentUserScore; \/\/ \u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u0447\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.  const encoder = new TextEncoder('utf-8'); \/\/ \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438 \"\u043a\u043b\u0438\u043a\u0430\u0445\". let msg = encoder.encode(JSON.stringify({     type: \"increment\",     username: \"John Doe\", }));   \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f. async function connectWT() {     document.getElementById('event-log').innerHTML = \"\";     const url = document.getElementById('url').value;     username = document.getElementById('username').value;     msg = encoder.encode(JSON.stringify({         type: \"increment\",         username: username,     }));     try {         var transport = new WebTransport(url);         addToEventLog('\u0418\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435...');     } catch (e) {         addToEventLog('\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. ' + e, 'error');         return;     }     try {         await transport.ready;         addToEventLog('\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0433\u043e\u0442\u043e\u0432\u043e.');     } catch (e) {         addToEventLog('\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c.' + e, 'error');         return;     }      transport.closed         .then(() =&gt; {             addToEventLog('\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.');         })         .catch(() =&gt; {             addToEventLog('\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043f\u0440\u0435\u0440\u0432\u0430\u043b\u043e\u0441\u044c.', 'error');         });      currentTransport = transport;     streamNumber = 1;      await createDatagramWriter();     readDatagrams(transport);      await createBiStream();     readFromIncomingStream();      document.getElementById('sendDataFrame').disabled = false;     document.getElementById('sendDataDStream').disabled = false;     document.getElementById('connect').value = 'Reconnect'; }  \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b. async function sendDatagram() {     try {         await currentTransportDatagramWriter.write(msg);         addToEventLog('\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0430: ' + msg);     } catch (e) {         addToEventLog('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0434\u0430\u043d\u043d\u044b\u0445: ' + e, 'error');     } } \/\/ \u0418\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u0430\u043a \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0443. async function createDatagramWriter() {     let transport = currentTransport;     try {         currentTransportDatagramWriter = transport.datagrams.writable.getWriter();         addToEventLog('\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c \u0433\u043e\u0442\u043e\u0432\u043e.');     } catch (e) {         addToEventLog('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f: ' + e, 'error');         return;     } }  \/\/ \u0418\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a. async function createBiStream() {     let transport = currentTransport;     try {         currentBiStream = await transport.createBidirectionalStream();         readableBiStream = currentBiStream.readable;         writableBiStream = currentBiStream.writable;         biStreamWriter = writableBiStream.getWriter();     } catch (e) {         addToEventLog('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430: ' + e, 'error');     } }  \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a. async function sendBiStream() {     let biStream = currentBiStream;     try {         let writer = biStreamWriter;         await writer.write(msg);         addToEventLog(             '\u041e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a #' + streamNumber +             ' with msg: ' + msg         );     } catch (e) {         addToEventLog('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u043e\u0442\u043e\u043a: ' + e, 'error');     } }  \/\/ \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0438\u0437 |\u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0430| \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \/\/ \u043f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442 EOF. async function readDatagrams(transport) {   try {     var reader = transport.datagrams.readable.getReader();     addToEventLog('\u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c \u0433\u043e\u0442\u043e\u0432.');   } catch (e) {     addToEventLog('\u041f\u0440\u0438\u0435\u043c \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f: ' + e, 'error');     return;   }   let decoder = new TextDecoder('utf-8');   try {     while (true) {       const { value, done } = await reader.read();       if (done) {         addToEventLog('\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c!');         return;       }       let data = decoder.decode(value);       updateUserScore(data);       addToEventLog('\u0414\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0430: ' + data);     }   } catch (e) {     addToEventLog('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0447\u0442\u0435\u043d\u0438\u0438 \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c: ' + e, 'error');   } }  \/\/ \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0438\u0437 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \/\/ \u043f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442 EOF. async function readFromIncomingStream() {     let decoder = new TextDecoder('utf-8');     const reader = readableBiStream.getReader();     try {         while (true) {             const { value, done } = await reader.read();             if (done) {                 addToEventLog('Stream #' + streamNumber + ' closed');                 return;             }             let data = decoder.decode(value);             updateUserScore(data);             addToEventLog('\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 #' + streamNumber + ': ' + data);         }     } catch (e) {         addToEventLog(         'Error while reading from stream #' + streamNumber + ': ' + e, 'error');         addToEventLog('    ' + e.message);     } }  \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043b\u043e\u0433 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435. function addToEventLog(text, severity = 'info') {   let log = document.getElementById('event-log');   let mostRecentEntry = log.lastElementChild;   let entry = document.createElement('li');   entry.innerText = text;   entry.className = 'log-' + severity;   log.appendChild(entry);    if (mostRecentEntry != null &amp;&amp;       mostRecentEntry.getBoundingClientRect().top &lt;           log.getBoundingClientRect().bottom) {     entry.scrollIntoView();   } }   \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u0447\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. function updateUserScore(data) {   let scoreElement = document.getElementById('userScore');   let score = '?';   try {     let response = JSON.parse(data);     score = response.score;   } catch (_) {     let response   }   scoreElement.innerText = score; }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>clicker.html<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;!doctype html&gt; &lt;html lang=\"ru\"&gt; &lt;title&gt;\u041f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043b\u0438\u043a\u0435\u0440 \u0447\u0435\u0440\u0435\u0437 WebTransport \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439&lt;\/title&gt; &lt;meta charset=\"utf-8\"&gt; &lt;script src=\"clicker.js\"&gt;&lt;\/script&gt; &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;  &lt;style&gt;     body {     font-family: sans-serif;   }    h1 {     margin: 0 auto;     width: fit-content;   }    h2 {     border-bottom: 1px dotted #333;     font-size: 120%;     font-weight: normal;     padding-bottom: 0.2em;     padding-top: 0.5em;   }    #top {     display: flex;     flex-direction: row-reverse;     flex-wrap: wrap;     justify-content: center;   }    #tool {     flex-grow: 1;     margin: 0 auto;     max-width: 26em;     padding: 0 1em;     width: 26em;   }    .input-line {     display: flex;   }    .input-line input[type=text] {     flex-grow: 1;     margin: 0 0.5em;   }    textarea {     height: 3em;     width: 100%;   }    #connect  {     margin-top: 0.5em;     margin-right: 0.5em;    }   #sendDataFrame, #sendDataDStream  {     margin-top: 0.5em;     width: 100%;   }    #event-log {     border: 1px dotted black;     font-family: monospace;     height: 12em;     overflow: scroll;     padding-bottom: 1em;     padding-top: 1em;   } &lt;\/style&gt;  &lt;body&gt; &lt;div id=\"top\"&gt;     &lt;div id=\"tool\"&gt;         &lt;h1&gt;\u041a\u043b\u0438\u043a\u0435\u0440&lt;\/h1&gt;         &lt;p&gt;\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0435\u0431 \u043a\u043b\u0438\u043a\u0435\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 WebTransport \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439.&lt;\/p&gt;         &lt;div&gt;             &lt;h2&gt;\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 WebTransport&lt;\/h2&gt;             &lt;div class=\"input-line\"&gt;                 &lt;label for=\"url\"&gt;Host:Port\/Path:&lt;\/label&gt;                 &lt;input type=\"text\" name=\"url\" id=\"url\"                        value=\"https:\/\/localhost:4433\/clicker\"&gt;             &lt;\/div&gt;             &lt;div class=\"input-line\"&gt;                 &lt;label for=\"username\"&gt;\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c:&lt;\/label&gt;                 &lt;input type=\"text\" name=\"username\" id=\"username\"                        value=\"John Doe\"&gt;             &lt;\/div&gt;             &lt;div style=\"text-align: right\"&gt;                 &lt;input type=\"button\" id=\"connect\" value=\"Connect\" onclick=\"connectWT()\"&gt;             &lt;\/div&gt;          &lt;\/div&gt;         &lt;div&gt;             &lt;form name=\"clicker\"&gt;                 &lt;input type=\"button\" id=\"sendDataFrame\" name=\"sendDataFrame\" value=\"\u041a\u043b\u0438\u043a \u0447\u0435\u0440\u0435\u0437 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u0443\"                        disabled onclick=\"sendDatagram()\"&gt;                 &lt;input type=\"button\" id=\"sendDataDStream\" name=\"sendDataDStream\"                        value=\"\u041a\u043b\u0438\u043a \u0447\u0435\u0440\u0435\u0437 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a.\"                        disabled onclick=\"sendBiStream()\"&gt;             &lt;\/form&gt;         &lt;\/div&gt;         &lt;h1 id=\"userScore\"&gt;&lt;\/h1&gt;         &lt;div&gt;             &lt;h2&gt;\u0416\u0443\u0440\u043d\u0430\u043b \u0441\u043e\u0431\u044b\u0442\u0438\u0439&lt;\/h2&gt;             &lt;ul id=\"event-log\"&gt;             &lt;\/ul&gt;         &lt;\/div&gt;     &lt;\/div&gt; &lt;\/div&gt; &lt;\/body&gt; &lt;\/html&gt;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e. \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0443\u0436\u0435 \u043f\u043e\u0437\u0430\u0434\u0438 \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 &#171;\u043a\u043b\u0438\u043a\u0435\u0440\u0430&#187; \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438. <\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0442\u0435\u0445 \u043a\u0442\u043e \u0440\u0430\u043d\u0435\u0435 \u043d\u0435 \u0431\u044b\u043b \u0437\u043d\u0430\u043a\u043e\u043c \u0441 aioquic \u0438\u043b\u0438 \u0441 QUIC, \u0434\u0430\u043d\u043d\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u043f\u043e\u0434\u0442\u043e\u043b\u043a\u043d\u0435\u0442 \u043a \u0447\u0442\u0435\u043d\u0438\u044e \u0434\u0440\u0443\u0433\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. <\/p>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b \u0441\u0441\u044b\u043b\u043e\u043a \u0438\u0437 \u0441\u0442\u0430\u0442\u044c\u0438:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/08\/http3-core-concepts-part1\/\" rel=\"noopener noreferrer nofollow\">Part 1: HTTP\/3 History And Core Concepts<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/08\/http3-performance-improvements-part2\/\" rel=\"noopener noreferrer nofollow\">Part 2: HTTP\/3 Performance Features<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/09\/http3-practical-deployment-options-part3\/\" rel=\"noopener noreferrer nofollow\">Part 3: Practical HTTP\/3 Deployment Options<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.andy-pearce.com\/blog\/posts\/2023\/Mar\/http3-in-practice-quic\/\" rel=\"noopener noreferrer nofollow\">HTTP\/3 in Practice \u2014\u00a0QUIC<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><\/p>\n<div class=\"tm-article-poll-container\"><!--[--><\/p>\n<div class=\"tm-article-poll tm-article-poll_variant-bordered\">\n<div class=\"tm-notice tm-notice_positive tm-article-poll__notice\"><!----><\/p>\n<div class=\"tm-notice__inner\"><!----><\/p>\n<div class=\"tm-notice__content\" data-test-id=\"notice-content\"><!--[--><span>\u0422\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u043f\u0440\u043e\u0441\u0435. <a rel=\"nofollow\" href=\"\/kek\/v1\/auth\/habrahabr\/?back=\/ru\/articles\/837338\/&#038;hl=ru\">\u0412\u043e\u0439\u0434\u0438\u0442\u0435<\/a>, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430.<\/span><!--]--><\/div>\n<\/div>\n<\/div>\n<p><!--[--><\/p>\n<div class=\"tm-article-poll__header\">\u0414\u043e\u0432\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u043b\u0438 \u0432\u0430\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 WebTransport \u0438 HTTP\/3?<\/div>\n<div class=\"tm-article-poll__answers\"><!--[--><\/p>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">0% <\/span><span class=\"tm-article-poll__answer-label\">\u0414\u0430<\/span><span class=\"tm-article-poll__answer-votes\">0<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 0%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent tm-article-poll__answer-percent_winning\">0% <\/span><span class=\"tm-article-poll__answer-label\">\u041d\u0435\u0442<\/span><span class=\"tm-article-poll__answer-votes\">0<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress tm-article-poll__answer-progress_winning\" style=\"width: 0%\"><\/div>\n<\/div>\n<\/div>\n<p><!--]--><\/div>\n<div class=\"tm-article-poll__stats\"> \u041d\u0438\u043a\u0442\u043e \u0435\u0449\u0435 \u043d\u0435 \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u0430\u043b.   \u0412\u043e\u0437\u0434\u0435\u0440\u0436\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u043d\u0435\u0442. <\/div>\n<p><!--]--><\/div>\n<div class=\"tm-article-poll tm-article-poll_variant-bordered\">\n<div class=\"tm-notice tm-notice_positive tm-article-poll__notice\"><!----><\/p>\n<div class=\"tm-notice__inner\"><!----><\/p>\n<div class=\"tm-notice__content\" data-test-id=\"notice-content\"><!--[--><span>\u0422\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u043f\u0440\u043e\u0441\u0435. <a rel=\"nofollow\" href=\"\/kek\/v1\/auth\/habrahabr\/?back=\/ru\/articles\/837338\/&#038;hl=ru\">\u0412\u043e\u0439\u0434\u0438\u0442\u0435<\/a>, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430.<\/span><!--]--><\/div>\n<\/div>\n<\/div>\n<p><!--[--><\/p>\n<div class=\"tm-article-poll__header\">\u0417\u043d\u0430\u043a\u043e\u043c\u044b \u043b\u0438 \u0432\u044b \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 aioquic?<\/div>\n<div class=\"tm-article-poll__answers\"><!--[--><\/p>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">0% <\/span><span class=\"tm-article-poll__answer-label\">\u0414\u0430<\/span><span class=\"tm-article-poll__answer-votes\">0<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 0%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent tm-article-poll__answer-percent_winning\">100% <\/span><span class=\"tm-article-poll__answer-label\">\u041d\u0435\u0442<\/span><span class=\"tm-article-poll__answer-votes\">1<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress tm-article-poll__answer-progress_winning\" style=\"width: 100%\"><\/div>\n<\/div>\n<\/div>\n<p><!--]--><\/div>\n<div class=\"tm-article-poll__stats\"> \u041f\u0440\u043e\u0433\u043e\u043b\u043e\u0441\u043e\u0432\u0430\u043b 1 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.   \u0412\u043e\u0437\u0434\u0435\u0440\u0436\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u043d\u0435\u0442. <\/div>\n<p><!--]--><\/div>\n<div class=\"tm-article-poll tm-article-poll_variant-bordered\">\n<div class=\"tm-notice tm-notice_positive tm-article-poll__notice\"><!----><\/p>\n<div class=\"tm-notice__inner\"><!----><\/p>\n<div class=\"tm-notice__content\" data-test-id=\"notice-content\"><!--[--><span>\u0422\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u043f\u0440\u043e\u0441\u0435. <a rel=\"nofollow\" href=\"\/kek\/v1\/auth\/habrahabr\/?back=\/ru\/articles\/837338\/&#038;hl=ru\">\u0412\u043e\u0439\u0434\u0438\u0442\u0435<\/a>, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430.<\/span><!--]--><\/div>\n<\/div>\n<\/div>\n<p><!--[--><\/p>\n<div class=\"tm-article-poll__header\">\u0415\u0441\u0442\u044c \u043b\u0438 \u0443 \u0432\u0430\u0441 \u0431\u043e\u043b\u0435\u0435 \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 aioquic?<\/div>\n<div class=\"tm-article-poll__answers\"><!--[--><\/p>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">0% <\/span><span class=\"tm-article-poll__answer-label\">\u0414\u0430 (\u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445)<\/span><span class=\"tm-article-poll__answer-votes\">0<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width: 0%\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent tm-article-poll__answer-percent_winning\">100% <\/span><span class=\"tm-article-poll__answer-label\">\u041d\u0435\u0442<\/span><span class=\"tm-article-poll__answer-votes\">1<\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress tm-article-poll__answer-progress_winning\" style=\"width: 100%\"><\/div>\n<\/div>\n<\/div>\n<p><!--]--><\/div>\n<div class=\"tm-article-poll__stats\"> \u041f\u0440\u043e\u0433\u043e\u043b\u043e\u0441\u043e\u0432\u0430\u043b 1 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.   \u0412\u043e\u0437\u0434\u0435\u0440\u0436\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u043d\u0435\u0442. <\/div>\n<p><!--]--><\/div>\n<p><!--]--><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/837338\/\"> https:\/\/habr.com\/ru\/articles\/837338\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0421\u0442\u0430\u0442\u044c\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u043e\u0439 \u043f\u0440\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 aioquic \u0438 \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f WebTransport. \u0417\u0430\u043c\u0435\u0442\u043a\u0430 \u0431\u044b\u043b\u0430 \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u043a\u0430\u043a \u0440\u0430\u0437\u0431\u043e\u0440 \u0447\u0443\u0436\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043f\u0440\u0438 \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0435 \u0441 aioquic. \u0417\u0430\u043c\u0435\u0442\u043a\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f QUIC \u0438 HTTP\/3 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 aioquic, \u043e\u043f\u0438\u0440\u0430\u044f\u0441\u044c \u043d\u0430 \u0441\u0442\u0430\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u0439 \u043f\u0440\u0438\u043c\u0435\u0440. \u0412 \u0445\u0443\u0434\u0448\u0438\u0445 \u0430\u043a\u0430\u0434\u0435\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u044f\u0445, \u043a \u0441\u0442\u0430\u0440\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0435 \u0431\u044b\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 &#171;\u0432\u043e\u0434\u0430&#187; \u043f\u0440\u043e \u043a\u043b\u0438\u043a\u0435\u0440 &#8212; \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<br \/>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u043c\u0443 \u043d\u0435 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430 &#171;\u0432\u043e\u0434\u0430&#187;, \u043b\u0443\u0447\u0448\u0435 \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0430 [<a href=\"https:\/\/WebTransport-aioquic\" rel=\"noopener noreferrer nofollow\">\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 WebTransport \u0432 Python \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f aioquic<\/a>].<\/p>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u0441\u0435\u0442\u0438, \u043f\u0440\u0438 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 (\u0431\u0443\u0434\u044c \u0442\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438\u043b\u0438 web-\u0441\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a), \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f &#171;\u043a\u043b\u0438\u043a\u0435\u0440&#187;. \u0421\u0443\u0442\u044c \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0441\u0442\u0430 &#8212; \u0447\u0438\u0442\u0430\u044e\u0449\u0435\u043c\u0443 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0443 \u0441 \u043e\u0434\u043d\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439, \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u043a\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443. \u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b. \u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e. \u042f \u0431\u044b \u0434\u0430\u0436\u0435 \u043c\u043e\u0433 \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043a\u0443\u0447\u043d\u044b\u043c\u0438, \u0435\u0441\u043b\u0438 \u0431\u044b \u043d\u0438 \u043d\u0435\u0434\u0430\u0432\u043d\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 \u0425\u043e\u043c\u044f\u043a\u043e\u043c (Hamster Combat). \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u0443 \u0442\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0435\u0441\u0442\u044c \u0432\u043e\u043f\u043b\u043e\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0445.<\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u043d\u0435 \u043c\u0430\u043b\u043e \u043b\u044e\u0434\u0435\u0439, \u0443\u0432\u0438\u0434\u0435\u0432 \u0442\u0430\u043a\u043e\u0439 \u0443\u0441\u043f\u0435\u0445 \u043a\u0430\u043a \u0443 \u0425\u043e\u043c\u044f\u043a\u0430, \u043f\u043e\u0431\u0435\u0436\u0430\u043b\u0438 \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0435\u0435. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u0438\u043c\u0447\u0438\u0432\u044b\u0435 \u043f\u043e\u0431\u0435\u0436\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u0438\u0442\u0438\u0440\u0443\u044e \u043a\u043b\u0438\u043a\u0438 (\u0442.\u0435. \u043f\u043e\u0448\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u043b\u043e\u043f\u0430\u0442\u044b). \u041d\u043e \u0434\u0430\u043b\u0435\u0435 \u043f\u043e\u0432\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0432\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u043b\u044e\u0434\u0435\u0439, \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u0435\u043b\u0435\u043c \u0434\u0430\u043d\u043d\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0431\u0443\u0434\u0435\u0442 John Doe, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c &#171;\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0443\u0441\u043f\u0435\u0445&#187;.<\/p>\n<blockquote>\n<p>(\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043f\u0440\u043e\u00a0\u043a\u043b\u0438\u043a\u0435\u0440 \u043d\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u0430\u044f \u0438\u00a0\u0431\u044b\u043b\u0430 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043d\u0430 \u043a\u0430\u043a \u00ab\u0432\u043e\u0434\u0430\u00bb \u043a\u00a0\u0437\u0430\u043c\u0435\u0442\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f\u00a0\u0431\u044b\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0440\u0430\u043d\u0435\u0435, \u043f\u0440\u0438\u00a0\u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0435 \u0441\u00a0\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 aioquic).<\/p>\n<\/blockquote>\n<h3>\u041f\u0440\u0438\u0447\u0435\u043c \u0442\u0443\u0442 WebTransport \u0438 HTTP\/3?<\/h3>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0433 \u0431\u044b\u0441\u0442\u0440\u043e \u043a\u043b\u0438\u043a\u0430\u0442\u044c \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0435, \u0430 \u0435\u0433\u043e \u0441\u0447\u0435\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u043b\u0441\u044f \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u043d\u0430\u0436\u0430\u0442\u0438\u0439 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443, \u0430 \u0442\u0430\u043a\u0436\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0431\u044b\u043b\u043e \u043b\u0438\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0430\u043d\u0438\u0439 (\u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439), \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0434\u0443\u043c\u0430\u0442\u044c\u0441\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c.<\/p>\n<blockquote>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0443\u0442\u043e\u0447\u043d\u0438\u043c, \u0447\u0442\u043e \u043f\u043e\u043a\u0430 \u043c\u044b \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043d\u0430\u0438\u0432\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0\u2014 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443.<\/p>\n<\/blockquote>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435, \u043e \u0447\u0435\u043c \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f \u043d\u0430\u0448 John Doe, \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u0437\u044b\u0432\u0447\u0438\u0432\u043e\u0433\u043e \u043a\u043b\u0438\u043a\u0435\u0440\u0430, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0433\u043e \u0442\u044b\u0441\u044f\u0447\u0430\u043c \u0447\u0435\u043b\u043e\u0432\u0435\u043a \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u00a0\u2014 \u044d\u0442\u043e \u0432\u044b\u0431\u043e\u0440 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0435\u0439 \u043a\u043b\u0438\u043a\u0435\u0440\u0430:<\/p>\n<ul>\n<li>\n<p><strong>REST API \u043d\u0430 \u0431\u0430\u0437\u0435 HTTP\/1.1<\/strong> &#8212; &#171;\u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e&#187; &#8212; \u043f\u043e\u0434\u0443\u043c\u0430\u043b John Doe. \u041e\u0434\u0438\u043d \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043b\u044f PUT \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443. \u0418 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043b\u044f GET \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0432 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u041e\u0434\u043d\u0430\u043a\u043e, \u0442\u0435, \u043a\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0437\u0443 \u0431\u0440\u043e\u0441\u0438\u043b\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434, \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c (\u0438\u043b\u0438 \u043d\u0430\u0433\u0443\u0433\u043b\u0438\u0442\u044c \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435) \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u0442\u0430\u043a\u043e\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043b\u0438\u0448\u043d\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0439, \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 TLS \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0438 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Head-of-line_blocking\" rel=\"noopener noreferrer nofollow\">Head-of-Line Blocking<\/a>). \u042d\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c-\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043a \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u043a \u043a\u043b\u0438\u043a\u0435\u0440\u0443 [\u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043d\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u043e\u0435 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0435\u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u043e].<\/p>\n<\/li>\n<li>\n<p><strong>WebSocket<\/strong> &#8212; &#171;\u0412\u043e\u0442 \u044d\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442&#187; &#8212; \u043f\u043e\u0434\u0443\u043c\u0430\u043b \u043d\u0430\u0448 John Doe, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0443\u0441\u043f\u0435\u043b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u0441 REST API \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u0440\u0443\u0442\u043e\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a <a href=\"https:\/\/fastapi.tiangolo.com\/\" rel=\"noopener noreferrer nofollow\">FastAPI<\/a> &#8212; &#171;\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u0432\u0435\u0434\u044c FastApi \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 WebSocket&#187;. WebSocket &#8212; \u044d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u0430\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c, \u043d\u043e \u043d\u0430\u0448 John Doe \u0443\u0441\u043f\u0435\u043b \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0438 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u043c\u0438 \u0442\u0438\u043f\u0430 &#171;&#8230; \u043d\u0430 \u0434\u0432\u043e\u0440\u0435 2024 \u0433\u043e\u0434, \u0437\u0430\u0447\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0438\u0437 2011 \u0433\u043e\u0434\u0430?&#187;. &#171;\u0418 \u0447\u0442\u043e \u0442\u043e\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c?&#187; &#8212; \u0437\u0430\u0434\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c \u043d\u0430\u0448 John Doe. \u0415\u0441\u0442\u044c \u0435\u0449\u0435 Long Polling, Server Sent Events, \u0430 \u0442\u0430\u043a\u0436\u0435 WebTransport.<\/p>\n<\/li>\n<li>\n<p><strong>WebTransport<\/strong> &#8212; \u044d\u0442\u043e \u043d\u043e\u0432\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043d\u0430 \u043d\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435 HTTP\/3. WebSockets \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 TCP, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043c\u0435\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f TCP, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u043b\u0430\u044e\u0442 \u0435\u0433\u043e \u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043a \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430\u043c (\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0435\u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445). WebTransport \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u043a\u0430\u043a \u043d\u0435\u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f UDP-\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0438 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 <a href=\"https:\/\/chromestatus.com\/feature\/4854144902889472\" rel=\"noopener noreferrer nofollow\">ref<\/a>. &#171;\u041d\u0443\u0436\u043d\u043e \u0431\u0440\u0430\u0442\u044c&#187; &#8212; \u0432\u043e\u0441\u043a\u043b\u0438\u043a\u043d\u0443\u043b John Doe \u0438 \u043f\u043e\u0448\u0435\u043b \u0447\u0438\u0442\u0430\u0442\u044c, \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0442\u043e\u0440\u043e\u0435, \u043e \u0447\u0435\u043c \u0437\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f John Doe &#8212; \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430. \u042d\u0442\u043e \u0442\u0435\u043c\u0430 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0438, \u0433\u0434\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043b\u043e\u0436\u0435\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440 \u0441\u0438\u0441\u0442\u0435\u043c \u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u0432(\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432) \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d \u043f\u0440\u0438\u043d\u0446\u0438\u043f CQRS, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u044f \u0438 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b. \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0435 Pub\/Sub. \u0418\u043b\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043e \u0431\u0440\u043e\u043a\u0435\u0440\u0430\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 socket.  \u0418 \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435\u043c \u043a\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0430 \u043e\u0434\u043d\u0430 \u0438 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0425\u043e\u0442\u044f \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 (\u043a\u043b\u0438\u043a\u0435\u0440) \u043c\u043d\u043e\u0433\u0438\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0438 \u043a \u0447\u0435\u043c\u0443.<\/p>\n<h2>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 WebTransport \u0432 Python \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f aioquic<\/h2>\n<blockquote>\n<p>\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0442\u043e\u0438\u0442 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044c, \u0447\u0442\u043e <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/draft-ietf-webtrans-http3\" rel=\"noopener noreferrer nofollow\">WebTransport<\/a> \u0435\u0449\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0447\u0435\u0440\u043d\u043e\u0432\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435.<\/p>\n<\/blockquote>\n<p><a class=\"anchor\" name=\"WebTransport-aioquic\" id=\"WebTransport-aioquic\"><\/a><\/p>\n<p>WebTransport &#8212; \u044d\u0442\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/draft-ietf-webtrans-overview-07\" rel=\"noopener noreferrer nofollow\">ref<\/a> \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0435\u0439\u0442\u0430\u0433\u0440\u0430\u043c\u043c, \u043e\u0434\u043d\u043e\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0438 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b HTTP\/3. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e WebTransport \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043f\u043e\u0432\u0435\u0440\u0445 HTTP\/3, \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0435\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0442\u043e\u043a\u0438 QUIC, \u0430 HTTP \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f &#171;\u0441\u0432\u043e\u0435\u0433\u043e \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u044f&#187;.<\/p>\n<p>\u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0435 \u0441 HTTP\/3 \u0438 QUIC \u044f \u043e\u0447\u0435\u043d\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/08\/http3-core-concepts-part1\/\" rel=\"noopener noreferrer nofollow\"><strong>Part 1: HTTP\/3 History And Core Concepts<\/strong><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/08\/http3-performance-improvements-part2\/\" rel=\"noopener noreferrer nofollow\"><strong>Part 2: HTTP\/3 Performance Features<\/strong><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2021\/09\/http3-practical-deployment-options-part3\/\" rel=\"noopener noreferrer nofollow\"><strong>Part 3: Practical HTTP\/3 Deployment Options<\/strong><\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 QUIC \u0438 HTTP\/3 \u043d\u0430 python \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <a href=\"https:\/\/aioquic.readthedocs.io\/en\/latest\/\" rel=\"noopener noreferrer nofollow\">aioquic<\/a>. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c async\/await \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u0438 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c asyncio. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0432\u0435\u0431 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 (\u043a\u0430\u043a \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 FastApi), \u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u0430\u0447\u0430\u0442\u044c \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0441 <a href=\"https:\/\/aioquic.readthedocs.io\/en\/latest\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0442\u043e\u0440\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u043a\u043e\u0434\u0430 \u0438\u0437 GoooleChrome GitHub <a href=\"https:\/\/github.com\/GoogleChrome\/samples\/tree\/gh-pages\/webtransport\" rel=\"noopener noreferrer nofollow\">GoogleChrome\/samples\/webtransport<\/a><\/p>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0442 GoooleChrome \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 Python \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c JavaScript. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 &#8212; \u044d\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0448\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0447\u0442\u0438 \u043d\u0430\u0448\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441 \u043a\u043b\u0438\u043a\u0435\u0440\u043e\u043c. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0432 \u043d\u0435\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f, \u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 &#171;\u043f\u043e\u0447\u0442\u0438&#187;.<\/p>\n<h3>\u0417\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u043e\u0442 GoooleChrome<\/h3>\n<p>\u041a\u043e\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043e\u0442 GoooleChrome<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043e\u0442 GoooleChrome<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">  # ref: https:\/\/github.com\/GoogleChrome\/samples\/tree\/gh-pages\/webtransport  import argparse import asyncio import logging from collections import defaultdict from typing import Dict, Optional  from aioquic.asyncio import QuicConnectionProtocol, serve from aioquic.h3.connection import H3_ALPN, H3Connection from aioquic.h3.events import H3Event, HeadersReceived, WebTransportStreamDataReceived, DatagramReceived from aioquic.quic.configuration import QuicConfiguration from aioquic.quic.connection import stream_is_unidirectional from aioquic.quic.events import ProtocolNegotiated, StreamReset, QuicEvent  BIND_ADDRESS = '::1' BIND_PORT = 4433  logger = logging.getLogger(__name__)  class CounterHandler:      def __init__(self, session_id, http: H3Connection) -&gt; None:         self._session_id = session_id         self._http = http         self._counters = defaultdict(int)      def h3_event_received(self, event: H3Event) -&gt; None:         if isinstance(event, DatagramReceived):             payload = str(len(event.data)).encode('ascii')             self._http.send_datagram(self._session_id, payload)          if isinstance(event, WebTransportStreamDataReceived):             self._counters[event.stream_id] += len(event.data)             if event.stream_ended:                 if stream_is_unidirectional(event.stream_id):                     response_id = self._http.create_webtransport_stream(                         self._session_id, is_unidirectional=True)                 else:                     response_id = event.stream_id                 payload = str(self._counters[event.stream_id]).encode('ascii')                 self._http._quic.send_stream_data(                     response_id, payload, end_stream=True)                 self.stream_closed(event.stream_id)      def stream_closed(self, stream_id: int) -&gt; None:         try:             del self._counters[stream_id]         except KeyError:             pass   class WebTransportProtocol(QuicConnectionProtocol):      def __init__(self, *args, **kwargs) -&gt; None:         super().__init__(*args, **kwargs)         self._http: Optional[H3Connection] = None         self._handler: Optional[CounterHandler] = None      def quic_event_received(self, event: QuicEvent) -&gt; None:         if isinstance(event, ProtocolNegotiated):             self._http = H3Connection(self._quic, enable_webtransport=True)         elif isinstance(event, StreamReset) and self._handler is not None:             self._handler.stream_closed(event.stream_id)          if self._http is not None:             for h3_event in self._http.handle_event(event):                 self._h3_event_received(h3_event)      def _h3_event_received(self, event: H3Event) -&gt; None:         if isinstance(event, HeadersReceived):             headers = {}             for header, value in event.headers:                 headers[header] = value             if (headers.get(b\":method\") == b\"CONNECT\" and                     headers.get(b\":protocol\") == b\"webtransport\"):                 self._handshake_webtransport(event.stream_id, headers)             else:                 self._send_response(event.stream_id, 400, end_stream=True)          if self._handler:             self._handler.h3_event_received(event)      def _handshake_webtransport(self,                                 stream_id: int,                                 request_headers: Dict[bytes, bytes]) -&gt; None:         authority = request_headers.get(b\":authority\")         path = request_headers.get(b\":path\")         if authority is None or path is None:             self._send_response(stream_id, 400,<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-429605","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/429605","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=429605"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/429605\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=429605"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=429605"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=429605"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}