我正在尝试制作一个简单的命令转发器,将我的家用电脑连接到我拥有的服务器,这样我就可以将命令推送到我的服务器,而我的家用电脑会得到它。这些命令对我的下载器来说是简单的暂停/恢复。我的设计是,在服务器上,我运行一个集线器实例,它创建一个用于传递命令的窗口和一个用于后端将这些命令传递到我的电脑的窗口。我将这两个“窗口”与一个 channel 绑定(bind)在一起,它们运行一个服务器。当客户端连接并向集线器发送消息时,它会通过 channel 流式传输到后端窗口,然后再到真正的后端(在我的家用电脑上)。当后端响应集线器上的后端窗口时,集线器将结果打印回客户端。
使用这种方法,只有第一条消息通过并与我的下载器一起工作。每次收到消息才能正常工作时,我都必须将家用电脑的后端与集线器重新连接。我不认为这是使用 websockets 的正确方法,所以我来了。在一个成功的请求后(当后端完成它的工作并回复结果时),它会永远循环并出现 EOF 错误。
代码的重要部分是:
如果你把源代码放在你的 GOPATH 中(我正在为支持现代 websockets 的 go 的尖端版本开发它),编译它:
go build gosab/cmd
,运行它:
./cmd -mode="hub"
hub./cmd -mode="backend"--address="localhost:8082"
后端
要将消息传递到集线器,请使用此 javascript:
var s = new WebSocket("ws://localhost:8082")
s.send("1 5")
那我该如何处理呢? channel 是在两个不同请求之间进行通信的好方法吗?
最佳答案
我很惊讶你还没有收到对此的答复。
您需要做的是类似于下面的代码。当您收到传入的 websocket 连接时,会为该连接生成一个新的 goroutine。如果你让那个 goroutine 结束,它会断开 websocket 客户端。
我假设您不一定要在同一台计算机上运行客户端和服务器。如果你总是这样,那么最好通过 channel 等在内部进行通信,而不是使用 websockets 或网络端口。我只提到这个,因为我不完全确定你用这个做什么。我只是希望我回答了你问题的正确部分。
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
}
}
关于io - 去 websockets eof,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9317392/