我是socket的新手,并尝试通过tcp套接字创建连接池 . 我的实现为每次调用发送32位长度然后发送二进制消息 . 但我有问题,有时读者从服务器接收先前的响应(可能发生在客户端关闭并重新 Build 套接字发送错误) . 如何在新请求之前刷新套接字(来自先前调用的剩余字节) . 有什么建议吗?
编辑:我知道tcp总是流0,如果我在消息之前发送byte(1),那么我可以有一个flush函数来检查socket在新调用之前是否为空 .
您的帖子实际上提出了几个问题:
如何管理连接池?
如何通过套接字处理通信?
这些实际上是两件不同的事情 . 连接池只是管理一组连接的一种方法 . 实现此目的的一种简单方法是使用如下类:
package netpool import ( "net" ) const MaxConnections = 3 type Error string func (e Error) Error() string { return string(e) } var ErrMaxConn = Error("Maximum connections reached") type Netpool struct { name string conns int free []net.Conn } func NewNetpool(name string) *Netpool { return &Netpool{ name: name, } } func (n *Netpool) Open() (conn net.Conn, err error) { if n.conns >= MaxConnections && len(n.free) == 0 { return nil, ErrMaxConn } if len(n.free) > 0 { // return the first free connection in the pool conn = n.free[0] n.free = n.free[1:] } else { addr, err := net.ResolveTCPAddr("tcp", n.name) if err != nil { return nil, err } conn, err = net.DialTCP("tcp", nil, addr) if err != nil { return nil, err } n.conns += 1 } return conn, err } func (n *Netpool) Close(conn net.Conn) error { n.free = append(n.free, conn) return nil }
我在这里创建了一个独立的课程 . 它通常作为更高级别类的一部分实现,例如MyHTTPHost或MyDatabase .
在这个简单的实现中,不会跟踪通过netpool.Open()返回的连接 . 可以通过调用Open(),然后关闭netpool.Close()之外的连接来泄漏连接 . 例如,如果要保留活动和非活动池,可以跟踪它们,这样可以解决此问题 .
您可能想要添加到池实现的其他几件事:
线程保护(例如,使用sync.Mutex)
在一段时间不活动后关闭freepool中的连接
错误检查以确保关闭的连接仍然有效
一旦 Build 连接,就可以正常调用Read和Write . 要刷新套接字上的所有数据,只需使用ioutil.ReadAll()辅助函数即可 . 默认情况下,如果没有可用数据,这将无限期阻止 . 为避免这种情况,请使用以下命令添
conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) _, err = ioutil.ReadAll(conn) neterr, ok := err.(net.Error) if ok && neterr.Timeout() { err = nil // timeout isn't an error in this case } if err != nil { // handle the error case. }
这将读取给定连接中的所有数据(如果有任何未决),或者如果没有数据待处理,将在500ms后返回I / O超时错误 .
类型断言是必需的,因为ioutil.ReadAll()返回一个Error接口,而不是net.Error接口,我们需要后者能够轻松找出是否由于超时而返回的调用 .
1 回答
您的帖子实际上提出了几个问题:
如何管理连接池?
如何通过套接字处理通信?
这些实际上是两件不同的事情 . 连接池只是管理一组连接的一种方法 . 实现此目的的一种简单方法是使用如下类:
我在这里创建了一个独立的课程 . 它通常作为更高级别类的一部分实现,例如MyHTTPHost或MyDatabase .
在这个简单的实现中,不会跟踪通过netpool.Open()返回的连接 . 可以通过调用Open(),然后关闭netpool.Close()之外的连接来泄漏连接 . 例如,如果要保留活动和非活动池,可以跟踪它们,这样可以解决此问题 .
您可能想要添加到池实现的其他几件事:
线程保护(例如,使用sync.Mutex)
在一段时间不活动后关闭freepool中的连接
错误检查以确保关闭的连接仍然有效
一旦 Build 连接,就可以正常调用Read和Write . 要刷新套接字上的所有数据,只需使用ioutil.ReadAll()辅助函数即可 . 默认情况下,如果没有可用数据,这将无限期阻止 . 为避免这种情况,请使用以下命令添
这将读取给定连接中的所有数据(如果有任何未决),或者如果没有数据待处理,将在500ms后返回I / O超时错误 .
类型断言是必需的,因为ioutil.ReadAll()返回一个Error接口,而不是net.Error接口,我们需要后者能够轻松找出是否由于超时而返回的调用 .