以下是一个 go 教程的聊天服务器例子,例子的 S 端 C 端都没问题。 为什么我用网络调试助手 tcp client 可以连上,但是发信息收不到呢?我在 S 端的很多位置都 fmt.Println 了都找不到。
//以下是服务端 // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. // License: creativecommons.org/licenses/by-nc-sa/4.0/ // See page 254. //!+ // Chat is a server that lets clients chat with each other. package main
import ( "bufio" "fmt" "log" "net" )
//!+broadcaster type client chan<- string // an outgoing message channel
var ( entering = make(chan client) leaving = make(chan client) messages = make(chan string) // all incoming client messages )
func broadcaster() { clients := make(map[client]bool) // all connected clients for { select { case msg := <-messages: // Broadcast incoming message to all // clients' outgoing message channels.
for cli := range clients {
cli <- msg
fmt.Println(msg)
}
case cli := <-entering:
clients[cli] = true
case cli := <-leaving:
delete(clients, cli)
close(cli)
}
}
}
//!-broadcaster
//!+handleConn func handleConn(conn net.Conn) { ch := make(chan string) // outgoing client messages go clientWriter(conn, ch)
who := conn.RemoteAddr().String()
ch <- "You are " + who
messages <- who + " has arrived"
entering <- ch
input := bufio.NewScanner(conn)
for input.Scan() {
messages <- who + ": " + input.Text()
fmt.Println(222)
}
// NOTE: ignoring potential errors from input.Err()
leaving <- ch
messages <- who + " has left"
conn.Close()
}
func clientWriter(conn net.Conn, ch <-chan string) { for msg := range ch { fmt.Fprintln(conn, msg) // NOTE: ignoring network errors } }
//!-handleConn
//!+main func main() { listener, err := net.Listen("tcp", "localhost:8000") if err != nil { log.Fatal(err) }
go broadcaster()
for {
conn, err := listener.Accept()
fmt.Println(111)
if err != nil {
log.Print(err)
continue
}
go handleConn(conn)
}
} //!-main
//以下是客户端 // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. // License: creativecommons.org/licenses/by-nc-sa/4.0/ // See page 227. // Netcat is a simple read/write client for TCP servers. package main
import ( "io" "log" "net" "os" )
//!+ func main() { conn, err := net.Dial("tcp", "localhost:8000") if err != nil { log.Fatal(err) } done := make(chan struct{}) go func() { io.Copy(os.Stdout, conn) // NOTE: ignoring errors log.Println("done") done <- struct{}{} // signal the main goroutine }() mustCopy(conn, os.Stdin) conn.Close() <-done // wait for background goroutine to finish }
//!-
func mustCopy(dst io.Writer, src io.Reader) { if _, err := io.Copy(dst, src); err != nil { log.Fatal(err) } }
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.