【go语言 socket编程系列】TCPConn类型与net.DialTCP方法

【TCPConn】
net.TCPConn是允许服务端与客户端之间的全双工通信的Go类型。其定义在tcpsock.go文件。

其定义如下

type TCPConn struct {conn
}

注意到 conn 是小写的c,其定义在net.go文件中,源码如下

type conn struct {fd *netFD
}

即conn是一个struct类型,只有一个指向netFD类型的  fd指针。 netFD定义在fd_unix.go中,其定义如下

即 netFD是一个网络文件描述符。

type netFD struct {// locking/lifetime of sysfd + serialize access to Read and Write methodsfdmu fdMutex// immutable until Closesysfd       int family      int sotype      int isConnected boolnet         stringladdr       Addrraddr       Addr// wait serverpd pollDesc
}

【常用方法】

func (c *conn) Read(b []byte) (int, error) 

其在net.go中定义如下

// Read implements the Conn Read method.
func (c *conn) Read(b []byte) (int, error) {if !c.ok() {return 0, syscall.EINVAL}   return c.fd.Read(b)
}

接受者c *conn 的Read方法 调用了fd成员的Read方法。其定义在fd_unix.go 中,源码如下:

func (fd *netFD) Read(p []byte) (n int, err error) {if err := fd.readLock(); err != nil {return 0, err}defer fd.readUnlock()if err := fd.pd.PrepareRead(); err != nil {return 0, &OpError{"read", fd.net, fd.raddr, err}}   for {n, err = syscall.Read(int(fd.sysfd), p)if err != nil {n = 0 if err == syscall.EAGAIN {if err = fd.pd.WaitRead(); err == nil {continue}   }   }   err = chkReadErr(n, err, fd) break}   if err != nil && err != io.EOF {err = &OpError{"read", fd.net, fd.raddr, err}}   return
}

func (c *conn) Write(b []byte) (int, error) 函数同Read一样,略。

【net.DialTCP方法】

func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) 主要用于创建一个TCPConn

net 参数为 tcp  tcp4  tcp6

laddr 为本地地址,通常为nil

raddr 为目的地址, 为TCPAddr类型的指针

函数返回一个 *TCPConn,可通过 Read 和Write 方法传递数据。

net,DialTCP定义在tcpsock_posix.go文件中,其源码如下

func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {switch net {case "tcp", "tcp4", "tcp6":default:return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}}   if raddr == nil {return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: errMissingAddress}}   return dialTCP(net, laddr, raddr, noDeadline)
}

主要通过调用私有函数dialTCP实现TCPConn的创建,dialTCP又会通过newTCPConn 来实现句柄的创建,最终会调用unix系统接口完成。

【代码实现】

调用net.DialTCP方法的代码demo

package mainimport ("fmt""io/ioutil""net""os"
)func main() {service := "www.baidu.com:80"tcpAddr, err := net.ResolveTCPAddr("tcp", service)checkError(err)fmt.Println("tcpAddr :")typeof(tcpAddr)myConn, err1 := net.DialTCP("tcp", nil, tcpAddr)checkError(err1)fmt.Println("myConn :")typeof(myConn)_, err = myConn.Write([]byte("HEAD / HTTP/1.1\r\n\r\n"))checkError(err)result, err := ioutil.ReadAll(myConn)checkError(err)fmt.Println(string(result))os.Exit(0)
}func typeof(v interface{}) {fmt.Printf("type is:%T\n", v)
}func checkError(err error) {if err != nil {fmt.Println("Error:", err.Error())os.Exit(1)}
}

编译执行如下

$./l_DialTCP 
tcpAddr :
type is:*net.TCPAddr
myConn :
type is:*net.TCPConn
HTTP/1.1 400 Bad Request
Server: nginx/1.13.5
Date: Wed, 26 Sep 2018 07:17:05 GMT
Content-Type: text/html
Content-Length: 173
Connection: close


$
 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部