From c793bb27437497792e9268dfac3cca03b17bbc87 Mon Sep 17 00:00:00 2001 From: TolaMironcenko Date: Tue, 8 Apr 2025 18:49:51 +0700 Subject: [PATCH] added websocket example --- websocket | Bin 0 -> 33784 bytes websocket.cpp | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100755 websocket create mode 100644 websocket.cpp diff --git a/websocket b/websocket new file mode 100755 index 0000000000000000000000000000000000000000..37d9d2370f0d119a49a02d8a81710f207ef80cbd GIT binary patch literal 33784 zcmeHw4SZD9weQInMkFL!XenA9K`Ba!nIyyjQWL_!1PDYzEcK%&lgWgPBs1w`5)#yF zG{iEdv8ffMeYE9ztv_n}T51I&D#nj8Xl?J%z9(F(ZQ81xX>3hxOH;At{ny%i&zw2T z>AM;4>wCZ7>w(NV>tnCI_S$Rjv(BC~``qSOzdAD`LsLhV_DPMfiur<4AsOYj$P<7H ztz4Ul&x^DRwQ0b!nI`xZ0)Q)yf~;hiE9pe0a*s;B8D1de6jT-xq;ghA!})@vpjIGo zDwjj2Hu}I}=KanTs3L49iZ@Oy)zx&2yxKK8tmxSn$c4p#~ zNV{aYU9y~lMI?YjLFG?UM}M`_pJrGA9vv0@scGhNL$aJ1ULxfcq&nyzNPjb=on~kQ zj}9AuCi<-IjbIa%Gux-|3MsFkva?o}dvc`^FvFLqgK;RR?7Rl$l#7ML-~W`|ply=% zS@qv8*$)cJ>e(knsDff`&4zj{vsW7-TNFP-%SggAO*qNU!XI@9mH*anoo`-L)A`zU z*WUcpoxi#2=gX^}Jb6W{x3R4Biq@vZtzKVe_u}sIvc+Ykg&qFFVlKB#)<^BG$SBa} zYegE-=va=wOWS5tmEN;r=d3+5s@6Ea{T*gle7u2%oR@;P4zyJCo6%vZ=o`?mRCMZ` zRP=ck^>)LNspQGOwiI^0W}$zzh5dJ)t!eX8=n0@hQq{Z1qP_1}=>Iq9Po?M7S*huz z7V>*7=)D&Haas8DE(>|Lh5nDBUA7ed`ILoxsfB-PE#&{r!p?74^y3dL;_Ay5{=d|s z-oqCC`)iAO*IMZLxJ5sH#zKC-h5Q1GdLPBSlPZ38Tj>9eg@68Jp~qpNr^SL^Vi7-f z3x7UuA^!=BxLRRh|5gk7V;22>n}z+O7J6J3{c_r(T_-H!yv?HC2T||2+FWh4Q4FR6 z_=S#1z>>FPm!K>8t>{ORzr9${PYIxDdiCZSy~z{sZ1r{oJ%Pnc_XGm|00gM6byKg*+wEve&&(@zILQ@s!M^kq*zM5ZcD1|Q-e3<~ z(bQVoC9Ltcb~wE0sjad*x=^w%SnBaLwWe~jV-s9oB09s5-tf5EsyFMKi*!d_8F@LK zJ}aiS_dQ4{Ub@nshIs$rbdY$6Z_5#P*c-i7>FXf^FSw z*By>c>!^mxG>yJ8;OX!Lx;*Jd06e|1u9PcJBl5~RIve3GM;rHe8Vc+sTRlPD)!OQJ zlT*3Zt(|5$+{#?-?T8eI979tdLQC5_J6iNcmwTH-j06ha+SQxt{B^p6yV;H@Kn&VO zSCg=qLNuN6T0*AE_;zFLv;Jbc*WUpPIy^e^+kh+3qkDbcAjI^o-Q9Y-C(z;dxmq#I z^sXYRcz0il}w?-P=4t4RbxZPD21SX&sowaOS2N3Nsc>43tl`xx7BDm69$W818PDj`4E^wJ&fS5Y_MktGb_AQ;ixv@DM%=de*;Y5| zBh1dF1bt0am0nUeiF665p}~SZQHNu~xNZ zOXbRH-425ir-e&}Dj{Y(FD$kr=gh>vEc_#wjn$4Utbj~oER*3`_!Qh};1Y-avak-7 zrJc=kibfiyY18>rXvkuHf=-|G?;Mn)T4Z_*n4!IfT$|Q!Z1}5P&~uIk&3^`s4w4;{ z{0iWYe(^rsVV$G>P10t0y;#XROUs=ubac-3f-_A!4>%p9|Dcq$0k!Z<%i zdtUNMe&xjd$jql}pOE@~`rU1~v(43(OT6d!cVS<)wp!xB%kIG)M3z=3@y~MkOic$) zhgv^`5FbUC2-qvv2NivEzMv1u`vgT-_^>YcFh0HpNR$x+9frk^V+Q(1;#5tG80c3R z=qC+yS_f0dsDZvz5drr|JEY>iWYpP?YL7b7E*@_6br$Hb@|FAga&wUL7A^IF~%Afli z1VZ$Wic|hP&>#?^&lRWqIou!+qMt8L`E#T}AVgQ+IS}Po1AU4!H?4f44L`T_&Jz(D`Ffj-AT zUudA)4D`zl^o0icA_Kk1K&Q1Gb(99d4q5FTOt zFyWMH#YPx^gzzlF4>0~P;gnj%_A&kd;gnLvh8X_};gm|ndKtfmaJsC;+8Mu#a7t@q z4UFGGIHgjtTE=$}PAOEZg7E<1=MY}R_)UaUDiyOa-bgs5P_Y8WuOpmNrrADz4#)}F65a9QK(Qgl z=Mqk-Ppp^m^9ZNZJJ!zlbiyeGiZw8vNjRlGv0BF8{UmTod14ieze6~sI z<2wka6eU){cz|$9O=3li-$Xd2BrzM~jf7Jw5-VW*I>IRhiD`^)BAjkgLkzrWh~%tV$m z)MljDgu;Om$oSZ!j zQq+yM9nE&X6N& zA8`&k_Ty}LXvjHOzaJPVdG{d>ouMB)L*eLOFa(86IJySIX~;R?fSz#lFuWRe?13UJ z?AZG*ssg7Msty1iAc;AU0KQM*xrkHX`^UPVa34wBhw+?$NZaMOf55TlnbF+Pv-yV{ z_h&>xjy-*jy}4t{2ON6`>i2}6`RTi%h;vWh=+(~9vutDNWh#FZJ&*GFM44rfi)RW9C?z&)3^fWw9{O?0EiOY&!CzLu7tdq<-qvSKPWDnTUM+u>_ z12;~*@SF&i+us`ICOqY&P7NKT`T2~f>DQUr-vB_dvzzh3{&pe{=IzByCnM+}CVA(e zln+NUxj};tD#OA9gH(YO-i<2&>_>~k(Ofo^Ji%zsUrFj2pb?6K(9fNre~;cvM5VmH zCE1wH2!szfL&p!(JWeVPl1m2qxnYC#U~wdzkv3FRhV$6;IY}z zwjF44=jHEw5H-cV!qvg@c&jP?(26rUqm&yJj=sf^+6tq>(T_p%SQdvtT*V8B*C9z1 z=KKYPl$5gR*R1G_dS03!=Y^v?!Hzyni1b3d-!VT#F+YqtL-i+}VaEiTppBJN*f|Fr z6V8lC{-Gi|qc9FVi?fqVLq-ypu>Uyp&aMJypJO6}%Pe<{29693-58H6C$7JyNDB8q z`FnT~7p}up;}ObGo~E=U`ej%d>K_5O?-1mV<^*_(vrcbS>2-OY7tGiy>IA7FoRicKAQA6y3Y%*{6D74b#p*>Ek zc+Sv?KRUmK%7{F`$`8}Zuc)z_G!6ETlRcsSQ2?Gt7#BsrEka2-HMF5G%cH+$wK)E!~-E2BdT#Ay#l%v8OkCPvqp;sXJL!u8JJc()zyu&nd!F`R?;$rtTT_#k8$v9X8)v-G< zk@P-ACThV8Q<#CkrxuT~Kl%@n)uH|<07o<91B2Wc73&V1kFpW9iC=Kl}e>4@ex zV)>1xj#-fz_%I9T&CKk}2T+(x9nG(tZRQ zG{xSb!DP&&@^`+8I%BU=#guf#ZM`0Kr@CPGQQfFzIaSIf4#+yZps1_ykfhZUtwPAD zuFfFMV;@Pbt`=dW3b)I`a|{Y=B`w=PE0VNvHtCE@{(p=MOTP$q^d&-!*ZK)u>&Kk~ zj&X5y#vMWdGJpx5ym7gk2^K`cQCwKGG2DX)>gfZLAL%lCNH$?d< zEVXg2f}|OD6Kn$+`Y<#MDcgjMXk&=-lX_}v^a$BP!Zp%2`5cjy%|MoO!7OqnP+1$@ zI+aty;I0T#qhoL)nGZZ1{S9}(GeD1VMv8&`i|8Gspzqd*)|roSb}wJeB>YbaG{VJb@O0#qP`&?H*=3a9$ny0V-hho4+IUd7uyuN9U3xx0ulZaCxqPZwKp7;Lg1! z6kQ+sC9XasP0x8_zI2=*u`76l35h|H5a~C`#P6aGaxLL#8!C_P zCxrU4@A>lUD{rX0F&^4BczA*bj0h(57h+Vja3$Lvjy}%`k1>=u)8bH4H{lE8Jw-|O zz>U=R6iuU2*CDiuk_7H`+~RORdAR%PW$&_A|3tHej1LTgaP;dWgS!iyKESO|cXJ4j zA`V{}Nbd?|sB}{R>Ex@DEV>*;6XUCZT|(n#fI~)>*bgDY z{2=C-iTpz(Gme|)@@Mn!9l24CWH=Q!2Z>me(r^llDUkOKXn~b20~+J3mL~Ks*?*WqCgIfX)Yg* z4*r(Zq2ufKfCMY~qP>QwVaEv1TFI*4qx$82{>wa{7?%*1j1`LDNAtqbL%i;C63UZS z5FY0`!_m*e@aVS*iO(vkZ{+}x^MJs}%iTsVBYuX~ha9`shicAPToNln!?5%*_DzT; z1~~gn$45XP9m0Xp4%xU{tH`ZX91RIm79f4Ji>@CDu}=u^!+SOR1eqt&9Bx+qE|96W z(N|3VeT-V0!eg>KzQ(RO!(*SLVzA?Cu%kPKj{OO*k!PIn%rN5bz?rdk04TXUlCN69HUep*?9+}DLE!{#17 zL1NsgfA`ASPSqI3&_c8!iZ+a543VKx=*85+QND$&97vjsJ_l0LWHgkxSj}e3Xfje3 z6sXv84%8Mv`2>yQ%fz%fkjn(oM|W^dbX^WdKM9R6FjYhS zZ)Bn*JTE#RR4e?>DCcFw4AmAWkM+Gp9uYQC3PjmWut-$SZI4K^jsZe#J^s)I>=Pbu zSCM@QZML}A#pRSlm5nc=E9C`5P5j(FNe%figp@jUW#+6=Gzby3^x2MS&^kVrO}dlk zF=v=2RP+KW4Oh@tRO+0TNVLRthwKysq3_mFEw~6JfN}>=M^G#A=NLC$7*3Feu^i5$ z^7m;el1Z{Ch_74~?kR zZmd>+_182LQTT?V$8oMYPjxZ(|Iw!rCR+4*+=w1c^sgzEAA%aR8Mf2?D(6bD7#Xy% znARWSmL~hF@78gxlY(Mm>~h)8ap&L+3E>*&@owMR2Z>X_(*|4$pnoV_^>#zOPmQP>jYIHYwnzy!iZ`#({=JU6I zHqa65?AqSlv!lpfTvEEE?8@?`i|G4NK8lx=J1SRKE?MkYYA;<}dgZFh#Y>k|RW7bt zQn|8dRaNgrMjsG5Vbmwd-10{jdlEF_~Lb*o@LM!`6~EaD~b<9 z9=F9Mloh?G_jWB0DHa{h&6{hluov2G_9DBjZo4<=Zo%*BY_$P@(C@}?aPp?tw{H!& znmo&F+dYlqDfGPQReqn(;|_ZLzGXJa&zqiXPbEKV4wLexQ(a}Hi^+9p4;l{-qb=~5 z@C2H~?f~sk_SzwE9)Zi?fB5tZWM|}l;D_O`0dffnaG#l7qG`ro2QIV4e@q5TZOs9H zo6XnR+G_K5*nIw=tqV`ZH<5B2ZkLZp;-?ulJodh9Sr=O957=5=fvui^E!g7n+1gy) zI{jE-;bmF|j`OpYAH&pMj`B^fO-{at^PQuUldl8b`pe152Qg_sj0x{0zz5!#oTT5p zX1+N&ISW(j-MGEG1o%F{Re(PMYyunwybAoaxcj~V&AyFlIH>M1$-Uw zQNV26oBjas62K?007PqUnOLo92kZvi1NdXWCjs99d=+pO*4y3#v;kg##iC_^R{=Hw zHUNGHSD{^iPXg`-d=c;%;OkgB9S7WrCFEJSi{1}d3OEhR{5Jru1?&a93veIc9>5X6 zhXF?c7vd`jdT8|~KpWtbfE9q#@nuT`U|zH+hw zmH<+!vl6fYa2sGR;4#2`fFH)f=m_9az)`>eAU*i}G@uRecYqau^hGKi89O#<8QldL z=g&ARcL@DR^b7E}=jW4?3rJwqS)5E=f>V64qBZ;sde9Hr%!1W3=d8^?XM1k1cJ
    )1*t3d^le+%Gd@cB7X#cxaS_k!OHKE7bqG{vt@ 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 console.log(e.data) +// ws.send('hello') + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +// Base64 кодирование (упрощенная версия) +string base64_encode(const string &in) { + const string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + string out; + int val = 0, valb = -6; + + for (unsigned char c : in) { + val = (val << 8) + c; + valb += 8; + while (valb >= 0) { + out.push_back(base64_chars[(val >> valb) & 0x3F]); + valb -= 6; + } + } + + if (valb > -6) + out.push_back(base64_chars[((val << 8) >> (valb + 8)) & 0x3F]); + + while (out.size() % 4) + out.push_back('='); + + return out; +} + +// Генерация ответа для WebSocket handshake +string get_websocket_accept(const string &client_key) { + const string magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + string combined = client_key + magic; + + unsigned char digest[SHA_DIGEST_LENGTH]; + SHA1(reinterpret_cast(combined.c_str()), combined.size(), digest); + + return base64_encode(string(reinterpret_cast(digest), SHA_DIGEST_LENGTH)); +} + +// Демаскировка данных +void unmask_data(char *data, size_t len, const char *mask) { + for(size_t i = 0; i < len; i++) { + data[i] ^= mask[i % 4]; + } +} + +int main() { + const int port = 8080; + + // Создание сокета + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd < 0) { + cerr << "Ошибка создания сокета" << endl; + return 1; + } + + // Настройка адреса + sockaddr_in address; + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(port); + + // Бинд и листен + if (bind(server_fd, (sockaddr*)&address, sizeof(address)) < 0) { + cerr << "Ошибка бинда" << endl; + return 1; + } + + if (listen(server_fd, 1) < 0) { + cerr << "Ошибка листена" << endl; + return 1; + } + + cout << "Сервер запущен на порту " << port << endl; + + while(true) { + // Принятие соединения + sockaddr_in client_addr; + socklen_t client_len = sizeof(client_addr); + int client_socket = accept(server_fd, (sockaddr*)&client_addr, &client_len); + + if (client_socket < 0) { + cerr << "Ошибка принятия соединения" << endl; + continue; + } + + // Чтение HTTP-запроса + char buffer[4096] = {0}; + read(client_socket, buffer, 4096); + + // Поиск ключа WebSocket + string request(buffer); + size_t key_pos = request.find("Sec-WebSocket-Key: "); + if(key_pos == string::npos) { + cerr << "Неверный WebSocket запрос" << endl; + close(client_socket); + continue; + } + + key_pos += 19; + size_t key_end = request.find("\r\n", key_pos); + string client_key = request.substr(key_pos, key_end - key_pos); + + // Формирование ответа + string response = "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + get_websocket_accept(client_key) + "\r\n\r\n"; + + send(client_socket, response.c_str(), response.size(), 0); + + // Цикл обработки сообщений + while(true) { + char header[2]; + if(recv(client_socket, header, 2, 0) <= 0) break; + + // Парсинг заголовка + unsigned char opcode = header[0] & 0x0F; + bool masked = (header[1] & 0x80) != 0; + size_t len = header[1] & 0x7F; + + // Чтение расширенной длины + if(len == 126) { + char ext_len[2]; + recv(client_socket, ext_len, 2, 0); + len = (ext_len[0] << 8) | ext_len[1]; + } else if(len == 127) { + cerr << "64-битная длина не поддерживается" << endl; + break; + } + + // Чтение маски + char mask[4]; + if(masked) recv(client_socket, mask, 4, 0); + + // Чтение данных + vector data(len); + recv(client_socket, data.data(), len, 0); + if(masked) unmask_data(data.data(), len, mask); + + // Обработка opcode + if(opcode == 0x8) { // Закрытие + cout << "Закрытие соединения" << endl; + break; + } + + // Эхо-ответ + unsigned char response_header[2] = {0x81, static_cast(len)}; + send(client_socket, reinterpret_cast(response_header), 2, 0); + send(client_socket, data.data(), len, 0); + } + + close(client_socket); + } + + close(server_fd); + return 0; +}