Go语言学习草稿(11) 网络编程

TCP和UDP

package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"strconv"
	"strings"
	"time"
)

// TCP服务器
func tcpServer() {
	listener, err := net.Listen("tcp", "127.0.0.1:20001")
	if err != nil {
		fmt.Println("启动TCP服务器失败, 原因是:", err)
		return
	}
	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("Accept 失败, 原因是:", err)
			return
		}
		go handleRequest(conn)
	}
}

// 处理客户端连接
func handleRequest(conn net.Conn) {
	defer conn.Close()
	var tmp = [128]byte{}
	n, err := conn.Read(tmp[:])
	if err != nil {
		fmt.Println("读取数据失败, 原因是:", err)
		return
	}
	fmt.Println(string(tmp[:n]))
}

// TCP客户端
func tcpClient(i int) {
	conn, err := net.Dial("tcp", "127.0.0.1:20001")
	defer conn.Close()
	if err != nil {
		fmt.Println("连接失败, 原因是:", err)
		return
	}
	// 发送数据
	conn.Write([]byte("Hello world from " + strconv.Itoa(i)))
}

// CS结构测试
func tcpConnectTest() {
	go tcpServer()
	time.Sleep(time.Second)
	for i := 0; i < 10; i++ {
		tcpClient(i)
	}
	time.Sleep(time.Second * 5)
}

// 解决粘包问题
// 客户端发送时会等待一段时间, 如果后面还有数据会连在一起发
// 发送数据时要先发长度
func pkgSplicing() {
	server := func() {
		listener, _ := net.Listen("tcp", "127.0.0.1:20002")
		for {
			conn, _ := listener.Accept()
			go func(conn net.Conn) {
				defer conn.Close()
				reader := bufio.NewReader(conn)
				var buf = make([]byte, 64)
				for {
					// 先尝试读取4个字节
					lengthByte := [4]byte{}
					n, err := reader.Read(lengthByte[:])
					if err == io.EOF {
						break
					}
					// 将4个字节解析成整数 作为长度
					var length int32 = 0
					binary.Read(bytes.NewBuffer(lengthByte[:]), binary.LittleEndian, &length)
					// 读取指定长度的内容
					n, _ = reader.Read(buf[:length])
					fmt.Println("服务器收到数据", string(buf[:n]))
				}
			}(conn)
		}
	}
	client := func() {
		conn, _ := net.Dial("tcp", "127.0.0.1:20002")
		defer conn.Close()
		for i := 0; i < 20; i++ {
			bytesToSend := []byte("Hello World!")
			binary.Write(conn, binary.LittleEndian, int32(len(bytesToSend))) // 写入的数据必须是定长的, in32,float32可以int不行
			_, _ = conn.Write(bytesToSend)
		}
	}
	go server()
	time.Sleep(time.Second)
	go client()
	time.Sleep(time.Second * 5)
}

// UDP服务器
func UDPServer() {
	conn, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   net.IPv4(127, 0, 0, 1),
		Port: 20003,
	})
	if err != nil {
		fmt.Println("listen UDP failed,", err)
		return
	}
	defer conn.Close() // 如果没有错误才关闭
	var data = [1024]byte{}
	for {
		n, addr, err := conn.ReadFromUDP(data[:])
		if err != nil {
			fmt.Println("ReadFromUDP failed,", err)
			return
		}
		fmt.Println(string(data[:n]))
		// 发送数据
		n, err = conn.WriteToUDP([]byte(strings.ToUpper(string(data[:n]))), addr)
	}
}

func UDPClient() {
	socket, err := net.DialUDP("udp", nil, &net.UDPAddr{
		IP:   net.IPv4(0, 0, 0, 0),
		Port: 20003,
	})
	if err != nil {
	    fmt.Println("连接服务器失败,", err)
	    return
	}
	defer socket.Close()
	_, err = socket.Write([]byte("I love you"))
	reply := make([]byte, 1024)
	n, _, err := socket.ReadFromUDP(reply[:])
	fmt.Println(string(reply[:n]))
}

func udpConnectTest() {
	go UDPServer()
	time.Sleep(time.Second)
	UDPClient()
	time.Sleep(time.Second)
}

HTTP

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

/*标题HTTP*/

// net/http 服务器
func httpServer() {
	// 简单的HTTP处理函数
	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		str := "<h1>Hello World!</h1>" // 传字符串
		writer.Write([]byte(str))

		bytes, _ := ioutil.ReadFile("go-learn/bin/new.txt") // 文件内容直接被发送出去
		writer.Write(bytes)
	})
	// HTTP请求处理: 测试request API
	http.HandleFunc("/query", getParamsOfRequest())
	http.ListenAndServe("127.0.0.1:20001", nil)
	// 然后打开浏览器输入127.0.0.1:20001就能看到Hello World!了
}

func httpServerTest() {
	httpServer()
}

// HTTP客户端
func httpClient() {
	response, err := http.Get("http://127.0.0.1:20001/query?name=wbq")
	if err != nil {
		fmt.Println("get url failed,", err)
		return
	}
	bytes, err := ioutil.ReadAll(response.Body) // 从reader中读
	if err != nil {
		fmt.Println("read response.Body failed,", err)
		return
	}
	fmt.Println(string(bytes)) // 打印ok
}

// 处理http请求的函数
func getParamsOfRequest() func(writer http.ResponseWriter, request *http.Request) {
	return func(writer http.ResponseWriter, request *http.Request) {
		query := request.URL.Query()
		name := query.Get("name") // 获得get请求中的参数 (可以直接获得中文)
		fmt.Println(name)

		fmt.Println(request.URL)                  // 输出 /query
		fmt.Println(request.Method)               // 输出 GET
		fmt.Println(ioutil.ReadAll(request.Body)) // 输出 [] <nil>

		writer.Write([]byte("ok"))
	}
}

func httpClientTest() {
	go httpServer()
	time.Sleep(time.Second)
	httpClient()
}

// 支持中文的http客户端
func httpClientWithChinese() {
	data := url.Values{}
	data.Set("name", "张飞")
	queryStr := data.Encode()

	urlObj, _ := url.Parse("http://127.0.0.1:20001/query")
	urlObj.RawQuery = queryStr

	request, _ := http.NewRequest("GET", urlObj.String(), nil)
	// -- 使用默认客户端
	// response, _ := http.DefaultClient.Do(request) // 使用默认客户端发送
	// -- 修改客户端配置并发送
	tr := &http.Transport{DisableKeepAlives: true} // 禁用 keep alive
	client := http.Client{Transport: tr} // client最好设置成全局变量
	response, _ := client.Do(request)
	// -- end
	defer response.Body.Close() // 关闭连接
	fmt.Println(ioutil.ReadAll(response.Body))
}

func httpClientWithChineseTest() {
	go httpServer()
	time.Sleep(time.Second)
	httpClientWithChinese()
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值