【go语言 socket编程系列】Conn接口类型及简单服务器实现Read Write 和Close方法

您所在的位置:网站首页 conn头 【go语言 socket编程系列】Conn接口类型及简单服务器实现Read Write 和Close方法

【go语言 socket编程系列】Conn接口类型及简单服务器实现Read Write 和Close方法

2023-08-22 12:25| 来源: 网络整理| 查看: 265

【Conn接口类型】

Conn是一种通用的面向流的网络连接,多个Goroutine可以同时调用Conn上的方法。

主要通过Read(b []byte)读取数据,Write(b [byte]) 写数据 及Close() 关闭连接。

其源码定义在net.go中

type Conn interface { Read(b []byte) (n int, err error) Write(b []byte) (n int, err error) Close() error LocalAddr() Addr RemoteAddr() Addr SetDeadline(t time.Time) error SetReadDeadline(t time.Time) error SetWriteDeadline(t time.Time) error }

【conn结构体】

conn结构体为一个 *netFD的网络文件描述符号,Conn接口方法都会作用在conn对象上。

type conn struct { fd *netFD }

Read(b []byte)

Read 方法用于从conn对象中读取字节流并写入[]byte类型的b对象中。 

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 }

Write(b [byte])

Write()方法用于把[]byte类型的切片中的数据写入到conn对象中

func (c *conn) Write(b []byte) (int, error) { if !c.ok() { return 0, syscall.EINVAL } n, err := c.fd.Write(b) if err != nil { err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} } return n, err }

Close()

Close()方法用于关闭conn连接。实现代码中会优先调用 ok()方法。

func (c *conn) Close() error { if !c.ok() { return syscall.EINVAL } err := c.fd.Close() if err != nil { err = &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} } return err } func (c *conn) ok() bool { return c != nil && c.fd != nil }

【一个简单的服务器实现】

工作流程:通过net.ListenTCP()生成一个mylistener对象,通过mylistener.Accept()方法接受客户端请求

handleRequest自定义函数中,预先申请[]byte类型的变量 mybuff,用于存放 从conn对象读取的数据。并通过Write()方法再写入到conn对象中。

package main import ( "fmt" "net" "os" ) func main() { service := ":2001" tcpAddr, err := net.ResolveTCPAddr("tcp", service) checkError(err) mylistener, err := net.ListenTCP("tcp", tcpAddr) checkError(err) for { conn, err := mylistener.Accept() if err != nil { continue } handleRequest(conn) conn.Close() } } func checkError(err error) { if err != nil { fmt.Println("Fatal error :", err.Error()) os.Exit(1) } } func handleRequest(conn net.Conn) { var mybuff [512]byte for { n, err := conn.Read(mybuff[0:]) if err != nil { return } fmt.Println(string(mybuff[0:])) fmt.Println("localaddr is:", conn.LocalAddr()) fmt.Println("remoteaddr is:", conn.RemoteAddr()) fmt.Println("##########") _, err2 := conn.Write(mybuff[0:n]) if err2 != nil { return } } } func checckError(err error) { if err != nil { fmt.Println("Fatal err:", err.Error()) os.Exit(1) } }

客户端通过 telnet命令简单实现,输入内容后回车,会直接打印到屏幕。

c$telnet localhost 2001 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. the first server the first server second second

服务端的显示如下

the first server localaddr is: 127.0.0.1:2001 remoteaddr is: 127.0.0.1:50120 ########## second t server localaddr is: 127.0.0.1:2001 remoteaddr is: 127.0.0.1:50120 ##########

从服务端的打印信息看, 有个“t server”的输出,其原因是 handleRequest函数中 定义的 mybuff是  [512]byte ,并通过mybuff[0:n]来写入数据。不同长度显示的会不一样。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3