W komunikacji websocket przy tworzeniu np. serwera ważne jest inicjowanie połączenia. Klient wysyła do serwera zwykłe żądanie GET, oprócz formatowania nagłówków trzeba odpowiedzieć na wysłany klucz.

Cały proces tworzenia serwera jest dostępny na stronie:
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers

W żądaniu handshake (zawsze GET), które może wyglądać tak jak w tym poradniku:

1
2
3
4
5
6
GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

mamy wpis
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

do którego teraz należy skonstruować na serwerze odpowiedź w postaci base64( SHA1( Sec-WebSocket-Key + GUID ))

GUID

Guid to unikalny ID serwera, można wygenerować sobie taki na stronie:
https://www.uuidgenerator.net/guid
i zapisać w stałej. To tzw. magic key.

SHA1

Przy tworzeniu SHA1 skorzystamy z darmowej biblioteki, której autorem jest Steve Reid:
https://github.com/clibs/sha1

Base64

Base64 – wykorzystamy kodowanie z biblioteki Apache:
https://opensource.apple.com/source/QuickTimeStreamingServer/QuickTimeStreamingServer-452/CommonUtilitiesLib/base64.c

Tu znajdziecie porównanie różnych algorytmów Base64, Apache jest jednym z najlepszych:
https://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c

Kodujemy w C

Pobieramy powyższe biblioteki – nie są potrzebne z nich wszystkie pliki, dwa najbardziej istotne to sha1.c oraz base64.c, załączamy pliki i korzystamy z nich. W przykładzie wykorzystałem dla sprawdzenia dane z poradnika Mozilli z punktu pierwszego.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "sha1.c"
#include "base64.c"

int main()
{
        char *magicTest = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; //36 znakow, GUID Magic string
        char shaSource[128] = "dGhlIHNhbXBsZSBub25jZQ=="; //24
        strcat(shaSource, magicTest); //laczymy te stringi w jeden do zakodowania
        printf("String kodowany: [%s]\n", shaSource);
        char result[32];//21
        SHA1(result, shaSource, strlen(shaSource) ); //Kodowanie SHA1
        char base64string[128];
        Base64encode(base64string, result, strlen(result)); //konwersja Base64
        printf("Po zakodowaniu to [%s] - dlugosc %i bajtow", base64string, strlen(base64string)); //wynikowy string, który wyślemy w odpowiedzi HandShake.
        return 0;
 }
C++