2013-10-31 19 views
11

Zaczynam bawić się z sieciami internetowymi + idź i dobrze Myślę, że nie rozumiem czegoś zupełnie podstawowego z websockets w Go.Obsługa websocket w Go

Chciałbym po prostu słuchać połączenia internetowego i odpowiednio je przetwarzać. Jednak wszystkie przykłady, które widzę w Go za pomocą websocket, obsługują stronę internetową, która następnie łączy się z websem, czy jest to wymóg?

Poniżej znajduje się podstawowy serwer echo mam setup:

package main 

import (
    "fmt" 
    "code.google.com/p/go.net/websocket" 
    "net/http" 
) 

func webHandler(ws *websocket.Conn) { 
    var s string 
    fmt.Fscan(ws, &s) 
    fmt.Println("Received: ", s) 
} 

func main() { 
    fmt.Println("Starting websock server: ") 
    http.Handle("/echo", websocket.Handler(webHandler)) 
    err := http.ListenAndServe(":8080", nil) 
    if err != nil { 
    panic("ListenAndServe: " + err.Error()) 
    } 
} 

To javascript służy do podłączenia:

ws = new WebSocket("ws://localhost:8080/echo"); 
ws.onmessage = function(e) { 
    console.log("websock: " + e.data); 
}; 

Jednak to powoduje: websocket połączenia „WS:// localhost: 8080/echo "nie powiodło się: nieoczekiwany kod odpowiedzi: 403

Odpowiedz

15

Podczas pracy z websockets z Javascript, rzadko będziesz musiał czytać ramki Ctly. Szczerze mówiąc, nie jestem nawet pewien, jak to zrobić.

Na szczęście pakiet websocket ma już typ, Codec, który robi to za Ciebie. Moja sugestia polega na użyciu predefiniowanego kodeka websocket.Message do wiadomości Recieve i Send.

Wiadomość jest kodekiem do wysyłania/odbierania danych tekstowych/binarnych w ramce na połączeniu WebSocket. Aby wysłać/odebrać ramkę tekstową, użyj typu łańcucha. Aby wysłać/odebrać ramkę binarną, użyj [] typu bajtowego.

Korzystanie websocket.Message Twój webHandler będzie wyglądać mniej więcej tak:

func webHandler(ws *websocket.Conn) { 
    var in []byte 
    if err := websocket.Message.Receive(ws, &in); err != nil { 
     return 
    } 
    fmt.Printf("Received: %s\n", string(in)) 
    websocket.Message.Send(ws, in)  
} 

I nie, nie jest to wymóg, aby Go służy strony internetowej. Otrzymany błąd 403 nie musi dotyczyć Go ani pakietu websocket.

+0

Co oznacza przerwa w bloku? –

+1

@ElgsQianChen Przerwa jest najprawdopodobniej pozostałością po tym, gdy po raz pierwszy ustawiam opcję Odbieranie i wysyłanie w pętli for, aby zapobiec jej rozłączeniu po pierwszej wiadomości. Zamiast tego zmieniłem go na 'return'. – ANisus

+0

Ach, rozumiem. Dziękuję za wyjaśnienie. @isis. –

10

miałem podobny problem i problem 403 błąd jest związany jak Go traktuje http Origin header:

Handler to prosty interfejs do klienta przeglądarki websocket. Sprawdza domyślnie, czy nagłówek Origin jest prawidłowym adresem URL. Możesz sprawdzić websocket.Conn.Config(). Pochodzenie w func. Jeśli korzystasz z serwera zamiast programu Handler, możesz wywołać websocket.Origin i sprawdzić pochodzenie w funkcji Handshake. Tak więc, jeśli chcesz zaakceptować klienta spoza przeglądarki, który nie wysyła nagłówka Origin, możesz użyć serwera. to nie sprawdza pochodzenia w jego uścisku dłoni.

Aby wyłączyć sprawdzanie Origin, należy użyć coś takiego:

http.HandleFunc("/echo", 
    func (w http.ResponseWriter, req *http.Request) { 
     s := websocket.Server{Handler: websocket.Handler(webHandler)} 
     s.ServeHTTP(w, req) 
    }); 

Przynajmniej że rozwiązał problem dla mnie (serwera do komunikacji serwer websocket) i myślę, że może to rozwiązać problem oraz jeśli nagłówek początku nie pasuje.

+0

Szukam również sposobu wyłączenia kontroli pochodzenia. src/ondemand/server.go: 103: nie można używać func literal (type func (http.ResponseWriter, * http.Request)) jako typ http.Handler w argumencie do http.Handle: \t func (http.ResponseWriter, * http .Request) nie implementuje http.Handler (brak metody ServeHTTP) – coulix

+0

Hot damn, thank you! To rozwiązanie nie tylko zadziałało, ale pasuje do tego, co już mam! –