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发送信息
", c.RemoteAddr().String())
buf := make([]byte, 1024)
n, err := c.Read(buf)
if err != nil {
fmt.Printf("读取数据失败,%v
", err)
return
}
fmt.Printf("读取字节数为%d
", 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
", err)
}
reader := bufio.NewReader(os.Stdin) //os.Stdin 代表标准输入[终端]
for {
line, err := reader.ReadString('
')
if err != nil {
fmt.Println("读取终端数据错误")
return
}
line = strings.Trim(line, "
")
if line == "exit" {
fmt.Println("用户退出客户端")
break
}
conent, err := conn.Write([]byte(line + "
"))
if err != nil {
log.Fatal(err)
}
fmt.Printf("客户端发送了 %d 字节的数据到服务端
", conent)
}
}
func main() {
Client()
}