int socket(int domain, int type, int protocol);
SOCK_SEQPACKET类型的Socket:
- 数据发送方的Socket接口程序记录数据边界,并将其信息随着字节流一同被发往数据接收方。
- 数据接收方的Socket接口程序会根据数据边界把字节流切分成若干个字节流片段,并按照需要依次传递给应用程序。
一般会把0作为它的第三个参数值。其含义是让操作系统内核根据第一个参数和第二个参数的值自行决定Socket所使用的协议。
TCP/IP协议栈中的传输层协议
TCP/IP协议栈中的网络互连层协议
一个int类型的值。该值是作为socket唯一标识符的文件描述符。
主要会使用到标准库代码包net中的API。
func Listen(net, laddr string) (Listener, error)
示例:
listener, err := net.Listen("tcp", "127.0.0.1:8085")
含义:以何种协议来在给定的地址上监听。必须是面向流的协议。
TCP和SCTP都属于面向流的传输层协议,但不同的是:
- TCP协议实现程序无法记录和意识到任何消息边界,也无法从字节流分离出消息
- SCTP协议实现程序却可以做到这些的
含义:当前程序在网络中的标识
格式:“host:port” (如:127.0.0.1:1840
)
“host”代表IP地址或主机名
“port”则代表当前程序欲监听的端口号
conn, err := listener.Accept()
效果
流程会被阻塞,直到某台计算机上的某个应用程序与当前程序建立了一个TCP连接。
返回值
第一个返回值代表 当前TCP连接的net.Conn类型值
func Dial(network, address string) (Conn, error)
示例:
conn, err := net.Dial("tcp", "127.0.0.1:8085")
- 第一个(network)
和net类似(可以参考“1) 获取监听器”中net
参数),但种类更多(因为不需要建立连接)
因此,udp、udp4、udp6、ip, ip4和ip6都可以作为参数- 第二个(address)
对方地址,如:127.0.0.1:8080
func DialTimeout(network, address string, timeout time.Duration) (Conn, error)
timeout默认是纳秒,因此我们一般改成秒,使用如下:
conn, err = net.DialTimeout("tcp", "127.0.0.1:8085", 2*time.Second)
作用:
用来从Socket的接收缓冲区中读取数据
方法声明
Read(b []byte) (n int, err error)
参数
[]byte类型。
该参数的值相当于一个被用来存放从连接上接收到的数据的“容器”
它的长度完全由应用程序来决定。
使用示例
var dataBuffer bytes.Buffer
b := make([]byte, 10)
for {
n, err := conn.Read(b)
if err != nil {
if err == io.EOF {
fmt.Println("The connection is closed.")
conn.Close()
} else {
fmt.Printf("Read Error: %s\n", err)
}
break
}
dataBuffer.Write(b[:n])
}
切分数据:
reader := bufio.NewReader(conn)
获取切分后的数据:
line, err := reader.ReadBytes('\n')
和Read基本相同
Write(b []byte) (n int, err error)
writer := bufio.NewWriter(conn)
不接受任何参数并返回一个net.Addr类型的结果。
net.Addr 类型是一个接口类型。在它的方法集合中有两个方法法:
示例:
conn.LocalAddr().Network()
示例:
conn.RemoteAddr().String()
b := make([]byte, 10)
for {
conn.SetDeadline(time.Now().Add(2 * time.Second))
n, err := conn.Read(b)
// 省略若干条语句
}
conn.SetDeadline(time.Time{})