net包之TCPConn

  • FD file descriptor 文件信息
  • netFD 实现了各个系统对socket的封装

conn

该结构实现了Conn接口

type conn struct {
	fd *netFD
}

conn的方法

Read(b []byte) (n int, err error)
从连接中读取所有内容
			result, err := ioutil.ReadAll(conn)  //读取所有内容
			
			//读取指定长度的内容
			var buf [512]byte
			n, err := conn.Read(buf[0:])

			//不断的从连接读取..
			result := bytes.NewBuffer(nil)
			var buf [512]byte
			for {
			        n, err := conn.Read(buf[0:])
			        result.Write(buf[0:n])
			        if err != nil {
			                if err == io.EOF {
			                        break
			                }
			                return nil, err
			        }
			}
			return result.Bytes(), nil
		
Write(b []byte) (n int, err error)
向连接中写入数据,n是写入数据的大小
			_, err = conn.Write([]byte("GET / HTTP/1.0\r\n\r\n"))		
		
Close() error
关闭连接
LocalAddr() Addr
获取发送连接的本地IP和端口
RemoteAddr() Addr
获取目标主机的ip和端口
			tcpAddr, err := net.ResolveTCPAddr("tcp4", "www.baidu.com:80")
			conn, err := net.DialTCP("tcp", nil, tcpAddr)
			fmt.Println(conn.LocalAddr())    //	192.168.1.88:51164
			fmt.Println(conn.RemoteAddr())   //	220.181.111.147:80
		
SetDeadline(t time.Time) error
设置连接到期时间,就是连接超时时间
SetReadDeadline(t time.Time) error
设置连接读取到期时间
SetWriteDeadline(t time.Time) error
设置连接写入到期时间
SetReadBuffer(bytes int) error
设置操作系统连接相关接收缓冲区大小
SetWriteBuffer(bytes int) error
设置操作系统连接相关传输缓冲区大小
File() (f *os.File, err error)
返回网络文件信息

TCPConn

注意:该类型并没有实现PacketConn接口.这是和udp的不同

type TCPConn struct {
	conn
}

DialTCP

一旦客户端已经建立TCP服务, 就可以和对方设备"通话"了. 如果成功,该调用返回一个用于通信的TCPConn。客户端和服务器通过它交换消息。通常情况下,客户端使用TCPConn写入请求到服务器, 并从TCPConn的读取响应。持续如此,直到任一(或两者)的两侧关闭连接。客户端使用DialTCP()该函数建立一个TCP连接。

	DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error)

其中laddr是本地地址,通常设置为nil;raddr是一个服务的远程地址, net是一个字符串,根据您是否希望是一个TCPv4连接,TCPv6连接来设置为"tcp4", "tcp6"或"tcp"中的一个,当然你也可以不关心链接形式。

客户端可能发送的消息之一就是“HEAD”消息。这用来查询服务器的信息和文档信息。 服务器返回的信息,不返回文档本身。发送到服务器的请求可能是:

	"HEAD / HTTP/1.1\r\n\r\n"

来吧看一个完整的栗子:

package main

import (
	"fmt"
	"io/ioutil"
	"net"
	"os"
)

func main() {
	tcpAddr, err := net.ResolveTCPAddr("tcp4", "localhost:80")  //换成www.baidu.com:80试一试
	checkError(err)

	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	checkError(err)

	_, err = conn.Write([]byte("GET / HTTP/1.0\r\n\r\n"))  //发送http请求
	checkError(err)

	result, err := ioutil.ReadAll(conn)
	checkError(err)

	fmt.Println(string(result))

	os.Exit(0)
}

func checkError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
		os.Exit(1)
	}
}

TCPConn的方法

ReadFrom(r io.Reader) (int64, error)
从一个IO中读取数据
CloseRead() error
CloseWrite() error
SetLinger(sec int) error
SetKeepAlive(keepalive bool) error
即使没有任何通信,一个客户端可能希望保持连接到服务器的状态。
SetNoDelay(noDelay bool) error
设置操作系统是否延迟发送数据包,默认是无延迟的

TCPlistener

type TCPListener struct {
	fd *netFD
}

ListenTCP

在一个服务器上注册并监听一个端口。然后它阻塞在一个"accept"操作,并等待客户端连接。当一个客户端连接, accept调用返回一个连接(connection)对象

net参数可以设置为字符串"tcp", "tcp4"或者"tcp6"中的一个。如果你想监听所有网络接口,IP地址应设置为0,或如果你只是想监听一个简单网络接口,IP地址可以设置为该网络的地址。如果端口设置为0,O/S会为你选择一个端口。否则,你可以选择你自己的。需要注意的是,在Unix系统上,除非你是监控系统,否则不能监听低于1024的端口,小于128的端口是由IETF标准化。该示例程序选择端口1200没有特别的原因。TCP地址如下":1200"

让我们看个完整的栗子

package main

import (
	"fmt"
	"net"
	"os"
	"time"
)

func main() {
	tcpAddr, err := net.ResolveTCPAddr("tcp", ":1201")
	checkError(err)

	listener, err := net.ListenTCP("tcp", tcpAddr)
	checkError(err)

	for {
		conn, err := listener.Accept()
		if err != nil {
			continue
		}
		daytime := time.Now().String()
		conn.Write([]byte(daytime))
		conn.Close()
	}
}

func checkError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
		os.Exit(1)
	}
}
	

相比客户端服务器更要注意对错误的处理。服务器应该永远运行,所以,如果出现任何错误与客户端,服务器只是忽略客户端继续运行。否则,客户端可以尝试搞砸了与服务器的连接,并导致服务器宕机。

TCPListener方法

AcceptTCP() (c *TCPConn, err error)
接收TCP连接
Accept() (c Conn, err error)
接收,返回一个连接
Close() error
关闭监听
Addr() Addr
返回监听的网络地址
SetDeadline(t time.Time) error
设置监听到期时间
			listener.SetDeadline(time.Now().Add(time.Second * 30))
		
File() (f *os.File, err error)

关于长连接理论上的实现.

长连接,就是不断的连接.只要保证连接不断.服务端不断循环读取连接中的值,然后进行处理.发送结果就OK了.保持连接..发送.接受.

posted @ 2013-04-18 14:59  zhepama  阅读(4954)  评论(0编辑  收藏  举报