Go语言之Go语言网络编程
GO 语言网络编程
Go 语言Socket编程
TCP Socket
Go语言的 net 包中有一个 TCPConn 类型,可以用来建立 TCP 客户端和 TCP 服务器端间的通信通道,TCPConn 类型里有两个主要的函数:
func (c *TCPConn) Write(b []byte) (n int, err os.Error) func (c *TCPConn) Read(b []byte) (n int, err os.Error)
CPConn 可以用在客户端和服务器端来读写数据。
还有我们需要知道一个 TCPAddr 类型,它表示一个 TCP 的地址信息,其定义如下:
type TCPAddr struct { IP IP Port int }
在Go语言中通过 ResolveTCPAddr 可以获取一个 TCPAddr 类型,ResolveTCPAddr 的函数定义如下:
func ResolveTCPAddr(net, addr string) (*TCPAddr, os.Error)
参数说明如下:
- net 参数是 "tcp4"、"tcp6"、"tcp" 中的任意一个,分别表示 TCP(IPv4-only),TCP(IPv6-only) 或者 TCP(IPv4,IPv6) 中的任意一个;
- addr 表示域名或者 IP 地址,例如 "c.biancheng.net:80" 或者 "127.0.0.1:22"。
TCP server
我们可以通过 net 包来创建一个服务器端程序,在服务器端我们需要绑定服务到指定的非激活端口,并监听此端口,当有客户端请求到达的时候可以接收到来自客户端连接的请求。
net 包中有相应功能的函数,函数定义如下
func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) func (l *TCPListener) Accept() (c Conn, err os.Error)
ListenTCP 函数会在本地 TCP 地址 laddr 上声明并返回一个 *TCPListener,net 参数必须是 "tcp"、"tcp4"、"tcp6",如果 laddr 的端口字段为 0,函数将选择一个当前可用的端口,可以用 Listener 的 Addr 方法获得该端口。
案列:
server
package main import ( "fmt" "net" ) func echo(c *net.TCPConn) { defer c.Close() for { fmt.Printf("服务器再等待客户端%s发送信息\n", c.RemoteAddr().String()) buf := make([]byte, 1024) n, err := c.Read(buf) if err != nil { fmt.Printf("读取数据失败,%v\n", err) return } fmt.Printf("读取字节数为%d\n", n) fmt.Printf(string(buf[:n])) } } // Server 表示服务器端函数 func Server() { address := net.TCPAddr{ IP: net.ParseIP("127.0.0.1"), Port: 8000, } listener, err := net.ListenTCP("tcp4", &address) if err != nil { fmt.Println("错误") } defer listener.Close() for { conn, err := listener.AcceptTCP() if err != nil { fmt.Println("报错") } fmt.Printf("客户端ip地址为:%v ", conn.RemoteAddr().String()) go echo(conn) } } func main() { Server() }
client
package main import ( "bufio" "fmt" "log" "net" "os" "strings" ) // Client 表示客户端函数 func Client() { conn, err := net.Dial("tcp4", "127.0.0.1:8000") if err != nil { fmt.Printf("错误 %v\n", err) } reader := bufio.NewReader(os.Stdin) //os.Stdin 代表标准输入[终端] for { line, err := reader.ReadString(‘\n‘) if err != nil { fmt.Println("读取终端数据错误") return } line = strings.Trim(line, "\r\n") if line == "exit" { fmt.Println("用户退出客户端") break } conent, err := conn.Write([]byte(line + "\n")) if err != nil { log.Fatal(err) } fmt.Printf("客户端发送了 %d 字节的数据到服务端\n", conent) } } func main() { Client() }