Go语言网络编程

1.TCP服务端编程模型

1.图示

2.服务端处理流程

  • 1.监听端口
  • 2.接收客户端的连接
  • 3.创建goroutine,处理该连接
package main

import (
    "fmt"
    "net"
)

func handle(conn net.Conn)  {
    defer conn.Close()
    for {
	var buf[128]byte
	length, err := conn.Read(buf[:])
	if err != nil {
    	    fmt.Println("read from conn failed, err: ", err)
	    break
	}
	str := string(buf[:length])
	fmt.Println("receive from client, message: ", str)
    }
}

func main()  {
    fmt.Println("listen on 50000...")
    listen, err := net.Listen("tcp", "0.0.0.0:50000")
    if err != nil {
	fmt.Println("listen failed, err: \n", err)
	return
    }
    for {
	conn, err := listen.Accept()
	if err != nil {
	    fmt.Println("accept failed, err: ", err)
	continue
    }
	go handle(conn)
    }
}

3.客户端编程模式

  • 1.建立与服务端的连接
  • 2.进行数据收发
  • 3.关闭链接
package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
    "strings"
)

func main()  {
    conn, err := net.Dial("tcp", "localhost:50000")
    if err != nil {
	fmt.Println("Error dialing", err.Error())
	return
    }
    defer conn.Close()
    // 从终端获取用户输入
    inputReader := bufio.NewReader(os.Stdin)
    for {
	// 以换行符作为结束
	input, _ := inputReader.ReadString('\n')
	// 去除终端输入字符串前后的换行
	trimmedInput := strings.Trim(input, "\r\n")
	// 当用户输入Q,就退出
	if trimmedInput == "Q" {
	    return
	}
	_, err = conn.Write([]byte(trimmedInput))
	if err != nil {
	    fmt.Println("write failed, err: ", err)
    	    break
	}
    }
}

4.HTTP请求

  • 1.HTTP协议是基于TCP协议上的文本协议
  • 2.每行文本使用\r\n结尾,当连续两个\r\n时,表示整个数据包结束
package main

import (
    "fmt"
    "io"
    "net"
)

func main()  {
    conn, err := net.Dial("tcp", "www.baidu.com:80")
    if err != nil {
	fmt.Println("Error dialing", err.Error())
	return
    }
    defer conn.Close()
    data := "GET / HTTP/1.1\r\n"
    data += "HOST: www.baidu.com\r\n"
    data += "connection: close\r\n"

    _, errors := io.WriteString(conn, data)
    if errors != nil {
	fmt.Println("write string failed, err: ", err)
    }
    var buf[1024]byte
    for {
	length, err := conn.Read(buf[:])
	if err != nil || length == 0 {
	    break
	}
	fmt.Println(string(buf[:length]))
    }
}

2.UDP协议

1.说明

  • 1.用户数据报协议
  • 2.无连接,直接进行数据发送
  • 3.不可靠,没有时序
  • 4.实时性比较好,通常用于视频直播相关领域

2.UDP服务端

package main

import (
    "fmt"
    "net"
)

func main()  {
    listen, err := net.ListenUDP("udp", &net.UDPAddr{
	IP:   net.IPv4(0,0,0,0),
	Port: 8999,
	Zone: "",
    })

    if err != nil {
	fmt.Println("listen failed, err: ", err)
	return
    }

    for {
	var data [1024]byte
	count, addr, err := listen.ReadFromUDP(data[:])
	if err != nil {
    	    fmt.Println("read udp failed, err: ", err)
	    continue
	}
	fmt.Printf("data: %s addr: %v count %d\n", data[0:count], addr, count)
	_, errs := listen.WriteToUDP([]byte("hello client!"), addr)
	if errs != nil {
	    fmt.Println("write udp failed, err: ", errs)
	    continue
	}
    }
}

3.UDP客户端

package main

import (
    "fmt"
    "net"
)

func main()  {
    client, err := net.DialUDP("udp", nil, &net.UDPAddr{
	IP:   net.IPv4(127, 0, 0, 1),
	Port: 8999,
	Zone: "",
    })
    if err != nil {
	fmt.Println("连接失败:", err)
	return
    }
    defer client.Close()

    // 发送数据
    sendData := []byte("hello server!")
    _, errs := client.Write(sendData)
    if errs != nil {
	fmt.Println("发送数据失败:", errs)
	return
    }
    // 接收数据
    data := make([]byte, 4096)
    read, remoteAddr, errors := client.ReadFromUDP(data)
    if errors != nil {
	fmt.Println("读取数据失败:", errors)
	return
    }
    fmt.Println(read, remoteAddr)
    fmt.Println(string(data))
}
posted @ 2022-09-28 15:55  fatpuffer  阅读(367)  评论(0)    收藏  举报