介绍
Socket 起源于 Unix,基于 Unix 的一切皆文件的哲学,万物都可以用 open -> read/write -> close
模式来操作。
Go 语言支持的 IP 类型。
Go 语言的 net 包中定义了很多类型、函数和方法用于网络编程,其中 IP 的定义如下:
type IP []byte
net 包中有很多函数来操作 IP,其中 ParseIP(string) IP
会把一个 IPv4 或者 IPv6 的地址转化成 IP 类型。
package main
import (
"fmt"
"net"
"os"
)
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "Usage: %s ipaddr\n", os.Args[0])
os.Exit(1)
}
name := os.Args[1]
addr := net.ParseIP(name)
if addr == nil {
fmt.Println("Invalid address")
} else {
fmt.Println("The address is", addr.String())
}
}
TCP Socket
Go 语言中的 net 包中有一个类型 TCPConn
,这个烈性可以用来作为客户端和服务器端交互的通道,它主要有两个方法:
func (c *TCPConn) Write(b []byte) (n int, err os.Error)
func (c *TCPConn) Read(b []byte) (n int, err os.Error)
TCPConn 可以在客户端和服务器端来读写数据。
我们需要有一个 TCPAddr
类型,它表示一个 TCP 的地址信息,定义如下:
type TCPAddr struct {
IP IP
Port int
}
在 Go 语言中通过 ResolveTCPAddr
获取一个 TCPAddr
.
// net 参数是 tcp4 , tcp6 , tcp 中的任意一个。
// addr 表示域名或者地址 www.google.com:80 || 127.0.0.1:22 .
func ResolvTCPAddr(net, addr string) (*TCPAddr, os.Error)
TCP client
Go 语言通过 net 包中的 DialTCP 函数来建立一个 TCP 连接,并返回一个 TCPConn
类型的对象,当连接建立时服务器端也创建一个同类型的对象,此时客户端和服务器端通过各自拥有的 TCPConn
对象来进行数据交换。
一般情况下,客户但通过 TCPConn
将请求发送到服务器,服务器读取并解析来自客户但的请求,并返回迎丹信息,这个连接只有当任意一端关闭了连接之后才失效,不然这连接可以一直使用。
// net 参数是 tcp4 , tcp6 , tcp 中的任意一个。
// laddr 表示本机地址,一般设置为 nil
// raddr 表示远程服务器的地址
func DialTCP(net string, laddr, rddr *TCPAddr) (c *TCPConn, err os.ERror)
一个例子:
package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"unsafe"
)
func main() {
asClientConnToWebServer()
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
func asClientConnToWebServer() {
service := "www.chaos.luxe:80"
tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
checkError(err)
conn, err := net.DialTCP("tcp4", nil, tcpAddr)
checkError(err)
defer conn.Close()
_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n"))
checkError(err)
result, err := ioutil.ReadAll(conn)
checkError(err)
resultString := *(*string)(unsafe.Pointer(&result))
fmt.Println(resultString)
}
TCP Server
服务器端我们需要绑定服务到指定的非激活端口,并监听此端口。
func ListenTCP(net string, ladder *TCPAddr) (l *TCPListener, err os.Error)
func (l *TCPListener) Accept() (c Conn, err os.Error)
一个例子:
package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"time"
"unsafe"
)
func checkError(err error) {
if err != nil {
panic(err)
}
}
func RunAsServer() {
addr := "localhost:9091"
tcpAddr, err := net.ResolveTCPAddr("tcp4", addr)
checkError(err)
tcpListener, err := net.ListenTCP("tcp4", tcpAddr)
checkError(err)
defer tcpListener.Close()
for {
conn, err := tcpListener.Accept()
if err != nil {
fmt.Errorf("Accept error %v\n", err)
continue
}
go handleClient(conn)
}
}
func handleClient(conn net.Conn) {
defer conn.Close()
for {
daytime := time.Now().String()
// don't care about return value
conn.Write([]byte(daytime))
//conn.Close()
conn.R
result, err := ioutil.ReadAll(conn)
if err != nil {
fmt.Errorf("ReadAll error %v\n", err)
continue
}
resultString := *(*string)(unsafe.Pointer(&result))
fmt.Printf("receive => %s\n", resultString)
}
}
func main() {
//asClientConnToWebServer()
RunAsServer()
}
控制 TCP 连接
// 设置超时时间,客户端和服务器端都适用
func (c *TCPConn) SetTimeout(nesc int64) os.Error
// 设置客户端是否和服务器端一直保持连接。
func (c *TCPConn) SetKeepAlive(keepalive bool) os.Error
EOF
Power by TeXt.