• Golang 端口复用测试


    先给出结论:

    同一个进程,使用一个端口,然后连接关闭,大约需要30s后才可再次使用这个端口。

    测试

    首先使用端口9001连接服务端,发送数据,然后关闭连接,接着再次使用端口9001连接服务端,如果连接失败,间隔15s后,再次尝试,最多尝试3次,。

    client

    package main
    
    
    import (
    
    	"bufio"
    	"fmt"
    	"net"
    	"os"
    	"time"
    )
    
    
    func DialCustom(network, address string, timeout time.Duration, localIP []byte, localPort int)(net.Conn,error) {
    	netAddr := &net.TCPAddr{Port:localPort}
    
    	if len(localIP) != 0 {
    		netAddr.IP = localIP
    	}
    
    	fmt.Println("netAddr:", netAddr)
    
    	d := net.Dialer{Timeout: timeout, LocalAddr: netAddr}
    	return d.Dial(network, address)
    }
    
    
    func getOneConn() {
    
    	serverAddr := "127.0.0.1:8080"
    
    	// 172.28.172.180
    	//localIP := []byte{0xAC, 0x1C, 0xAC, 0xB4}  // IP
    	localIP := []byte{} //  any IP
    	localPort := 9001
    
    	var conn net.Conn
    	var err error
    
    	for i:=0;i<3;i++{
    
    		conn, err = DialCustom("tcp", serverAddr, time.Second*10, localIP,localPort)
    		if err != nil {
    			fmt.Println("dial failed:", err)
    			if i == 2 {
    				os.Exit(1)
    			}
    			time.Sleep(15*time.Second)
    		} else {
    			break
    		}
    	}
    
    	defer conn.Close()
    
    
    	buffer := make([]byte, 512)
    	reader := bufio.NewReader(conn)
    
    	n, err2 := reader.Read(buffer)
    	if err2 != nil {
    		fmt.Println("Read failed:", err2)
    		return
    	}
    
    	fmt.Println("count:", n, "msg:", string(buffer))
    
    }
    
    
    
    
    func main() {
    
    	getOneConn()
    	fmt.Println("=========================")
    	getOneConn()
    	fmt.Println("=========================")
    	select{}
    
    }
    
    

    server

    package main
    
    import (
    	"fmt"
    	"net"
    	"log"
    )
    
    func main() {
    
    	addr := "0.0.0.0:8080"
    
    	tcpAddr, err := net.ResolveTCPAddr("tcp",addr)
    
    	if err != nil {
    		log.Fatalf("net.ResovleTCPAddr fail:%s", addr)
    	}
    
    	listener, err := net.ListenTCP("tcp", tcpAddr)
    	if err != nil {
    		log.Fatalf("listen %s fail: %s", addr, err)
    	} else {
    	
    		log.Println("rpc listening", addr)
    	}
    
    
    	for {
    		conn, err := listener.Accept()
    		if err != nil {
    			log.Println("listener.Accept error:", err)
    			continue
    		}
    	
    		go handleConnection(conn)
    	
    	}
    
    }
    
    
    func handleConnection(conn net.Conn) {
    
    	//defer conn.Close()
    
    	var buffer []byte = []byte("You are welcome. I'm server.")
    
    	n, err := conn.Write(buffer)
    
    	if err != nil {
    	
    		fmt.Println("Write error:", err)
    	}
    	fmt.Println("send:", n)
    
    	fmt.Println("connetion end")
    
    }
    
    
    
    

    output

    client输出:

    $ ./client 
    netAddr: :9001
    count: 28 msg: You are welcome. I'm server.
    =========================
    netAddr: :9001
    dial failed: dial tcp :9001->127.0.0.1:8080: bind: address already in use
    
    
    netAddr: :9001
    dial failed: dial tcp :9001->127.0.0.1:8080: bind: address already in use
    
    netAddr: :9001
    count: 28 msg: You are welcome. I'm server.
    =========================
    

    经过3次重试,30s后,才可以重新使用同一个端口9001进行连接。也就是同一个进程的情况狂下,一个连接关闭后,端口大约30s后才可以被使用。

  • 相关阅读:
    110、抽象基类为什么不能创建对象?
    109、什么情况会自动生成默认构造函数?
    108、如果想将某个类用作基类,为什么该类必须定义而非声明?
    107、类如何实现只能静态分配和只能动态分配
    106、C++中的指针参数传递和引用参数传递有什么区别?底层原理你知道吗?
    hdoj--2036--改革春风吹满地(数学几何)
    nyoj--46--最少乘法次数(数学+技巧)
    vijos--P1211--生日日数(纯模拟)
    nyoj--42--一笔画问题(并查集)
    nyoj--49--开心的小明(背包)
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/9213025.html
Copyright © 2020-2023  润新知