到目前为止,我们已经区分了TCP的API和UDP的API,例如使用DialTCP和DialUDP分别返回TCPConn和UDPConn。 Conn类型是一个接口,TCPConn和UDPConn都实现了这个接口。 在很大程度上,您可以处理此接口而不是两种类型。
您可以使用dail函数,而不是TCP和UDP的单独功能
1
| func Dial(net, laddr, raddr string) (c Conn, err os.Error)
|
网络可以是“tcp”,“tcp4”(仅限IPv4),“tcp6”(仅限IPv6),“udp”,“udp4”(仅限IPv4),“udp6”(仅限IPv6), “ip”,“ip4”(仅限IPv4)和“ip6”仅限IPv6。 它将返回Conn接口的适当实现。 请注意,此函数采用字符串而不是地址作为raddr参数,因此使用此函数的程序可以避免首先生成地址类型。
之前写好的客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
package main
import ( "net" "os" "fmt" "io/ioutil" )
func main() { if len(os.Args) != 2 { fmt.Fprintf(os.Stderr, "Usage: %s host:port ", os.Args[0]) os.Exit(1) } service := os.Args[1]
tcpAddr, err := net.ResolveTCPAddr("tcp4", service) checkError(err)
conn, err := net.DialTCP("tcp", nil, tcpAddr) checkError(err)
_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n")) checkError(err)
result, err := ioutil.ReadAll(conn) checkError(err)
fmt.Println(string(result))
os.Exit(0) }
func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) os.Exit(1) } }
|
修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
package main
import ( "bytes" "fmt" "io" "io/ioutil" "net" "os" )
func main() { if len(os.Args) != 2 { fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0]) os.Exit(1) } service := os.Args[1]
conn, err := net.Dial("tcp", service) checkError(err)
defer conn.Close()
_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n")) checkError(err)
result, err := ioutil.ReadAll(conn) checkError(err)
fmt.Println(string(result))
os.Exit(0) }
func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) os.Exit(1) } }
|
对于服务器也有两个新的方法:
1 2
| func Listen(net, laddr string) (l Listener, err os.Error) func (l Listener) Accept() (c Conn, err os.Error)
|
之前的服务器例子可以修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
package main
import ( "fmt" "net" "os" )
func main() {
service := ":1200" listener, err := net.Listen("tcp", service) checkError(err)
for { conn, err := listener.Accept() if err != nil { continue } go handleClient(conn) } }
func handleClient(conn net.Conn) { defer conn.Close()
var buf [512]byte for { n, err := conn.Read(buf[0:]) if err != nil { return } _, err2 := conn.Write(buf[0:n]) if err2 != nil { return } } }
func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) os.Exit(1) } }
|
如果你想编写UDP服务器,那么有一个接口PacketConn和一个返回此实现的方法:
1
| func ListenPacket(net, laddr string) (c PacketConn, err os.Error)
|
此接口具有主要方法ReadFrom和WriteTo来处理数据包读取和写入。
灾难总是接踵而至,这正是世间的常理。你以为只要哭诉一下,就会有谁来救你?如果失败了,就只能说明我不过是如此程度的男人