2012-02-16 30 views
6

Tôi đang cố gắng tạo một giao diện lệnh đơn giản để kết nối máy tính ở nhà với máy chủ mà tôi sở hữu, để tôi có thể đẩy lệnh đến máy chủ và máy tính gia đình của mình nhận được. Các lệnh đó là tạm dừng/tiếp tục đơn giản cho trình tải xuống của tôi. Thiết kế của tôi là, trên một máy chủ, tôi chạy một thể hiện trung tâm, tạo ra một cửa sổ cho các lệnh truyền và một cửa sổ cho backend để truyền các lệnh đó đến máy của tôi. Tôi đang giới hạn hai "cửa sổ" đó với một kênh, họ chạy một máy chủ. Khi một khách hàng kết nối và gửi một tin nhắn đến trung tâm, nó sẽ được truyền qua một kênh đến cửa sổ phụ trợ và sau đó đến phần phụ trợ thực sự (trên máy tính gia đình của tôi). Khi phụ trợ đáp ứng với cửa sổ phụ trợ trên hub, hub sẽ in kết quả quay lại máy khách.go websockets eof

Với cách tiếp cận này, chỉ thư đầu tiên chuyển và làm việc với trình tải xuống của tôi. Tôi phải kết nối lại các phụ trợ từ máy nhà của tôi với trung tâm mỗi khi tôi nhận được một tin nhắn để có được điều này làm việc đúng cách. Tôi không nghĩ đó là cách thích hợp với websockets, vì vậy tôi ở đây. Sau khi một yêu cầu thành công (khi backend kết thúc công việc của nó và trả lời kết quả), nó được looped mãi mãi với lỗi EOF.

Các bộ phận quan trọng của mã là:

Nếu bạn đặt các nguồn trong GOPATH của bạn (tôi đang phát triển nó cho tip phiên bản đi để hỗ trợ các websockets hiện đại), để biên dịch nó: go build gosab/cmd, để chạy nó:

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

Để vượt qua các tin nhắn đến các trung tâm, sử dụng javascript này:

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

Vì vậy, làm thế nào để xử lý nó? Kênh có phải là cách hay để giao tiếp giữa hai yêu cầu khác nhau không?

+0

Tái phát minh bánh xe, có thể để giải trí? Nghe có vẻ giống như Salt: http://saltstack.org/ hoặc Puppet Labs Marionette: http://docs.puppetlabs.com/mcollective/index.html – djangofan

+0

các liên kết tốt, nhưng tôi muốn tự mình thực hiện một cái gì đó như thế này – farnoy

+0

I sử dụng một cái gì đó tương tự (một máy chủ trò chơi với giao tiếp trình duyệt-máy chủ trong websockets) vì vậy tôi biết làm thế nào để làm điều đó trong đi nhưng tôi không nhận được câu hỏi thực sự ở đây là gì.Nếu nó chỉ là "kênh là một cách tốt để giao tiếp", câu trả lời là CÓ. –

Trả lời

7

Tôi rất ngạc nhiên khi bạn chưa nhận được câu trả lời cho điều này.

Những gì bạn cần làm là một cái gì đó giống như mã bên dưới. Khi bạn nhận được một kết nối websocket đến, một goroutine mới được sinh ra cho kết nối đó. Nếu bạn cho rằng kết thúc goroutine, nó sẽ ngắt kết nối máy khách websocket.

Tôi đang giả định rằng bạn không nhất thiết phải chạy máy khách và máy chủ trên cùng một máy tính. Nếu bạn luôn như vậy, thì tốt nhất là nên thực hiện giao tiếp nội bộ qua các kênh hoặc thay vì sử dụng ổ cắm web hoặc cổng mạng. Tôi chỉ đề cập đến điều này bởi vì tôi không hoàn toàn chắc chắn những gì bạn đang sử dụng này cho. Tôi chỉ hy vọng tôi đã trả lời đúng phần câu hỏi của bạn.

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

trông rất hứa hẹn, một máy chủ điều khiển sự kiện đơn giản. Tôi sẽ cố gắng ý tưởng này khi tôi nhận được một thời gian, trong khi đó: 1 cho cố gắng để giúp – farnoy

+0

Nếu bạn không muốn kết nối được đóng lại tại sao bạn 'return' nếu một lỗi gặp phải ?, nên EOF trên tín hiệu kết nối chấm dứt? – Triztian