io包:studygolang.com/pkgdoc
bufio包:studygolang.com/pkgdoc
net包:studygolang.com/pkgdoc
Dial函数和服务端建立连接:
conn, err := net.Dial("tcp", "google.com:80")
if err != nil {
// handle error
}
fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
status, err := bufio.NewReader(conn).ReadString('\n')
// ...
Listen和accept函数创建的服务端:
ln, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
for {
conn, err := ln.Accept()
if err != nil {
// handle error
continue
}
go handleConnection(conn)
}
conn接口
type Conn interface {
// Read从连接中读取数据
// Read方法可能会在超过某个固定时间限制后超时返回错误,该错误的Timeout()方法返回真
Read(b []byte) (n int, err error)
// Write从连接中写入数据
// Write方法可能会在超过某个固定时间限制后超时返回错误,该错误的Timeout()方法返回真
Write(b []byte) (n int, err error)
// Close方法关闭该连接
// 并会导致任何阻塞中的Read或Write方法不再阻塞并返回错误
Close() error
// 返回本地网络地址
LocalAddr() Addr
// 返回远端网络地址
RemoteAddr() Addr
// 设定该连接的读写deadline,等价于同时调用SetReadDeadline和SetWriteDeadline
// deadline是一个绝对时间,超过该时间后I/O操作就会直接因超时失败返回而不会阻塞
// deadline对之后的所有I/O操作都起效,而不仅仅是下一次的读或写操作
// 参数t为零值表示不设置期限
SetDeadline(t time.Time) error
// 设定该连接的读操作deadline,参数t为零值表示不设置期限
SetReadDeadline(t time.Time) error
// 设定该连接的写操作deadline,参数t为零值表示不设置期限
// 即使写入超时,返回值n也可能>0,说明成功写入了部分数据
SetWriteDeadline(t time.Time) error
}
linux缓冲区
Linux系统默认的读写缓冲区大小是由内核参数决定的,具体大小取决于系统的配置和硬件性能。一般情况下,Linux系统的读写缓冲区大小是比较合理的,可以满足大部分应用程序的需求。 在Linux系统中,可以通过/sys/devices/system/node/nodeX/meminfo文件查看当前系统的内存使用情况,其中包括了缓冲区和缓存的大小。另外,可以通过sysctl命令查看和修改内核参数,其中包括了读写缓冲区的大小。 例如,可以使用以下命令查看当前系统的读写缓冲区大小:
sysctl net.core.rmem_default sysctl net.core.wmem_default sysctl net.core.rmem_max sysctl net.core.wmem_max其中,rmem_default和wmem_default表示TCP连接的默认读写缓冲区大小,rmem_max和wmem_max表示TCP连接的最大读写缓冲区大小。默认情况下,Linux系统的TCP连接的默认读写缓冲区大小为87380字节,最大读写缓冲区大小为16777216字节。
设置系统缓冲区的大小:func (c *conn) SetReadBuffer(bytes int) error
// SetReadBuffer 设置操作系统上此connection的的接收缓冲区的大小,
// TCP请求接收缓冲区是用来存储接收到的TCP数据包的地方。它的作用是在TCP连接的数据传输过程中,
// 暂时存储接收到的数据,等待应用程序处理。当TCP数据包到达时,它们会被存储在接收缓冲区中,
// 直到应用程序准备好处理它们。这样可以确保数据的可靠传输,因为如果数据包到达速度过快,
// 应用程序可能无法及时处理所有数据,导致数据丢失。同时,接收缓冲区还可以帮助控制TCP连接的流量,
// 避免过多的数据包拥塞网络,影响网络性能。因此,TCP请求接收缓冲区在TCP连接中起着非常重要的作用。
func (c *conn) SetReadBuffer(bytes int) error {
if !c.ok() {
return syscall.EINVAL
}
if err := setReadBuffer(c.fd, bytes); err != nil {
return &OpError{Op: "set", Net: c.fd.net, Source: nil, Addr: c.fd.laddr, Err: err}
}
return nil
}
func setReadBuffer(fd *netFD, bytes int) error {
err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
runtime.KeepAlive(fd)
return wrapSyscallError("setsockopt", err)
}
从tcpConn上读取数据包
// Read implements the Conn Read method.
func (c *conn) Read(b []byte) (int, error) {
if !c.ok() {
return 0, syscall.EINVAL
}
n, err := c.fd.Read(b)
if err != nil && err != io.EOF {
err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
}
return n, err
}