Go入门系列

Go入门系列(十)网络

2020-03-18  本文已影响0人  RabbitMask

目录
一、TCP编程
二、UDP编程

其实前几天买了本书,今天终于到货了,满怀欣喜的打开目录,socket编程、数据库、I/O统统没有,额。。。

回归正题,关于TCP/UDP的基础我们不做过多解释了,大家可自行补充或可参考python网络编程【python入门系列(十)】辅助理解,才不是打广告的说。

一、TCP编程

我们借助net包来模拟一个系统,服务端可以相应来自用户端的输入,借助我们之前学到的并发,允许它为多个用户提供连接,且通过循环持续响应用户请求,在收到exit时断开连接:

func Listen(network, address string) (Listener, error)
//network:选用的协议:TCP、UDP,    如:“tcp”或 “udp” 注意:只支持小写字母
//address:IP地址+端口号,             如:“127.0.0.1:8000”或 “:8000”

数据交互时,发送使用Write()方法,接收使用Read()方法。

func main() {
    listener, err := net.Listen("tcp", "127.0.0.1:8000")
    checkErr(err)
    defer listener.Close()

    for {
        conn, err := listener.Accept()
        checkErr(err)
        go task(conn)
    }
}
func task(conn net.Conn)  {
    defer conn.Close()
    addr :=  conn.RemoteAddr( ).String()
    fmt.Println(addr, " connect sucessful" )
    buf := make([ ]byte, 1024)
    for{
        n, err := conn.Read(buf)
        checkErr(err)
        if string(buf[:n])=="exit"{
            conn.Write([]byte("拜拜~~~~"))
            conn.Close()
            fmt.Println(addr, " Disconnect sucessful" )
            return
        }
        fmt.Printf("read buf = %s\n", string(buf[:n]))
        response:="Hello "+string(buf[:n])
        conn.Write([]byte(response))
    }
}

func checkErr(err error) {
    if err != nil {
        fmt.Println(err.Error())
        return
    }
}
#控制台
127.0.0.1:54815  connect sucessful
read buf = rabbit
read buf = carrot
127.0.0.1:54815  Disconnect sucessful

我们稍加总结下最重要的数据交互规则:

func taskdemo(c net.Conn) {
    //some code...

    //Simple read from connection
    buffer := make([]byte, 1024)
    c.Read(buffer)

    //simple write to connection
    c.Write([]byte("Hello from server"))
}
func Dial(network, address string) (Conn, error)
//network:选用的协议:TCP、UDP,如:“tcp”或 “udp”
//address:服务器IP地址+端口号, 如:“127.0.0.1:8000”或 “www.baidu.com:80”
func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:8000")
    if err != nil {
        fmt.Println("连接失败,错误:", err)
        return
    }
    defer conn.Close()
    for{
        var name string
        _, _ = fmt.Scanln(&name)
        conn.Write([]byte(name))

        buf := make([]byte,1024)
        n,_ := conn.Read(buf)
        fmt.Println(string(buf[:n]))
    }

}
#控制台
rabbit
Hello rabbit
carrot
Hello carrot
exit
拜拜~~~~

二、UDP编程

UDP连接是一个不负责任的连接,如果不允许你的消息丢包,那记得做好接收反馈,如果没有接收成功记得重发,但是UDP的特点在于它不需要持续的会话,意味着在某些场景下他更加隐匿,比如木马、木马、和木马。

func main() {
    udpAddr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:8000")
    listener, err := net.ListenUDP("udp", udpAddr)
    checkErr(err)
    fmt.Println("Start listening ... ")
    defer listener.Close()
    task(listener)
}

func task(conn *net.UDPConn)  {
    defer conn.Close()
    buf := make([ ]byte, 1024)
    for{
        n, addr, err := conn.ReadFromUDP(buf)
        checkErr(err)
        fmt.Printf("read buf = %s\n", string(buf[:n]))
        go func(){
            response:="Hello "+string(buf[:n])
            conn.WriteToUDP([]byte(response),addr)
        }()
    }
}

func checkErr(err error) {
    if err != nil {
        fmt.Println(err.Error())
        return
    }
}
#控制台
Start listening ... 
read buf = rabbit
read buf = carrot

我们将UDP的并发处理放到了闭包这里,另外我们对数据交互的规则简单整理下:

func taskdemo(c *net.UDPConn) {
    //some code...

    //simple read
    buffer := make([]byte, 1024)
    n, addr, err:= c.ReadFromUDP(buffer)

    //simple write to connection
    c.WriteToUDP([]byte("Hello from server"),addr)
}
func main() {
    conn, err := net.Dial("udp", "127.0.0.1:8000")
    if err != nil {
        fmt.Println("连接失败,错误:", err)
        return
    }
    defer conn.Close()
    for{
        var name string
        _, _ = fmt.Scanln(&name)
        conn.Write([]byte(name))

        buf := make([]byte,1024)
        n,_ := conn.Read(buf)
        fmt.Println(string(buf[:n]))
    }
}
#控制台
rabbit
Hello rabbit
carrot
Hello carrot

当然,像服务端一样,使用ReadFromUDP()方法和WriteToUDP()方法也是可以的。

上一篇下一篇

猜你喜欢

热点阅读