2012-02-16 14 views
6

Sto cercando di fare un semplice forwarder di comandi per connettere il mio computer di casa a un server che possiedo, in modo da poter inviare comandi al mio server e il mio pc di casa lo ottiene. Questi comandi sono semplici pause/riprendi per il mio downloader. Il mio progetto è che su un server, eseguo un'istanza hub, che crea una finestra per il passaggio dei comandi e una finestra per il back-end per passare quei comandi al mio pc. Lego queste due "finestre" con un canale, gestiscono un server. Quando un client si connette e invia un messaggio all'hub, viene trasmesso attraverso un canale alla finestra di back-end e quindi al back-end reale (sul mio PC di casa). Quando il backend risponde alla finestra di back-end sull'hub, l'hub stampa il risultato sul client.go socket eof

Con questo approccio, solo il primo messaggio passa e funziona con il mio downloader. Devo ricollegare il back-end dal mio pc di casa con l'hub ogni volta che ottengo un messaggio per farlo funzionare correttamente. Non penso che sia il modo giusto con le websocket, quindi eccomi qui. Dopo una richiesta riuscita (quando il backend termina è lavoro e risponde al risultato), viene interrotta per sempre con errore EOF.

Le parti importanti del codice sono:

Se si mette la fonte della tua GOPATH (sto sviluppando per la punta versione di go per supportare websocket moderni), per compilarlo: go build gosab/cmd, per eseguirlo:

  • ./cmd -mode="hub"hub
  • ./cmd -mode="backend" --address="localhost:8082"backend

per passare i messaggi al mozzo, utilizzare questo javascript:

var s = new WebSocket("ws://localhost:8082") 
s.send("1 5") 

Allora, come faccio gestire? I canali sono un buon modo per comunicare tra due richieste diverse?

+0

Reinventare la ruota, forse per divertimento? Sembra molto simile a Salt: http://saltstack.org/ o Puppet Labs Marionette: http://docs.puppetlabs.com/mcollective/index.html – djangofan

+0

buoni collegamenti, ma voglio implementare qualcosa di simile da solo – farnoy

+0

I usare qualcosa di simile (un server di gioco con comunicazione browser-server in websocket) quindi so come farlo, ma non capisco quale sia la vera domanda qui.Se è solo "i canali sono un buon modo per comunicare", la risposta è SI. –

risposta

7

Sono sorpreso che tu non abbia ricevuto una risposta a questo.

Quello che devi fare è qualcosa come il codice qui sotto. Quando si riceve una connessione websocket in arrivo, viene generata una nuova goroutine per quella connessione. Se lasci terminare quella goroutine, disconnetterà il client websocket.

Suppongo che non si eseguirà necessariamente il client e il server sullo stesso computer. Se lo sei sempre, allora sarebbe meglio fare la comunicazione internamente tramite canali o simili invece di usare websocket o una porta di rete. Lo dico solo perché non sono completamente sicuro di cosa stai usando. Spero solo di aver risposto alla parte giusta della tua domanda.

package main 

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

type Message struct { 
    RequestID  int 
    Command  string 
    SomeOtherThing string 
    Success  bool 
} 

var mode *string = flag.String("mode", "<nil>", "Mode: server or client") 
var address *string = flag.String("address", "localhost:8080", "Bind address:port") 

func main() { 
    flag.Parse() 

    switch *mode { 
    case "server": 
     RunServer() 
    case "client": 
     RunClient() 
    default: 
     flag.Usage() 
    } 
} 

func RunServer() { 
    http.Handle("/", http.FileServer(http.Dir("www"))) 
    http.Handle("/server", websocket.Handler(WSHandler)) 
    fmt.Println("Starting Server") 
    err := http.ListenAndServe(*address, nil) 
    if err != nil { 
     fmt.Printf("HTTP failed: %s\n", err.Error()) 
     os.Exit(1) 
    } 
} 

func WSHandler(ws *websocket.Conn) { 
    defer ws.Close() 
    fmt.Println("Client Connected") 
    for { 
     var message Message 
     err := websocket.JSON.Receive(ws, &message) 
     if err != nil { 
      fmt.Printf("Error: %s\n", err.Error()) 
      return 
     } 
     fmt.Println(message) 

     // do something useful here... 

     response := new(Message) 
     response.RequestID = message.RequestID 
     response.Success = true 
     response.SomeOtherThing = "The hot dog left the castle as requested." 
     err = websocket.JSON.Send(ws, response) 
     if err != nil { 
      fmt.Printf("Send failed: %s\n", err.Error()) 
      os.Exit(1) 
     } 
    } 
} 

func RunClient() { 
    fmt.Println("Starting Client") 
    ws, err := websocket.Dial(fmt.Sprintf("ws://%s/server", *address), "", fmt.Sprintf("http://%s/", *address)) 
    if err != nil { 
     fmt.Printf("Dial failed: %s\n", err.Error()) 
     os.Exit(1) 
    } 
    incomingMessages := make(chan Message) 
    go readClientMessages(ws, incomingMessages) 
    i := 0 
    for { 
     select { 
     case <-time.After(time.Duration(2e9)): 
      i++ 
      response := new(Message) 
      response.RequestID = i 
      response.Command = "Eject the hot dog." 
      err = websocket.JSON.Send(ws, response) 
      if err != nil { 
       fmt.Printf("Send failed: %s\n", err.Error()) 
       os.Exit(1) 
      } 
     case message := <-incomingMessages: 
      fmt.Println(message) 
     } 
    } 
} 

func readClientMessages(ws *websocket.Conn, incomingMessages chan Message) { 
    for { 
     var message Message 
     err := websocket.JSON.Receive(ws, &message) 
     if err != nil { 
      fmt.Printf("Error: %s\n", err.Error()) 
      return 
     } 
     incomingMessages <- message 
    } 
} 
+2

sembra molto promettente, un semplice server basato su eventi. Proverò questa idea quando avrò un po 'di tempo, nel frattempo: +1 per cercare di aiutare – farnoy

+0

Se non vuoi che la connessione sia chiusa, perché ritorni? Se si incontra un errore ?, dovrebbe EOF sul segnale di connessione? terminazione? – Triztian