• Golang client绑定本地IP和端口


    有时需要指定网络通信时本地使用的IP地址和端口号。

    在Go语言中可通过定义 Dialer 中LocalAddr 成员实现。
    Dialer结构定义如下:

    // A Dialer contains options for connecting to an address.
    //
    // The zero value for each field is equivalent to dialing
    // without that option. Dialing with the zero value of Dialer
    // is therefore equivalent to just calling the Dial function.
    type Dialer struct {
        ...
    
    	// LocalAddr is the local address to use when dialing an
    	// address. The address must be of a compatible type for the
    	// network being dialed.
    	// If nil, a local address is automatically chosen.
    	LocalAddr Addr
    }
    

    Addr是接口类型,其定义如下:

    // Addr represents a network end point address.
    //
    // The two methods Network and String conventionally return strings
    // that can be passed as the arguments to Dial, but the exact form
    // and meaning of the strings is up to the implementation.
    type Addr interface {
    	Network() string // name of the network (for example, "tcp", "udp")
    	String() string  // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80")
    }
    

    目前实现Addr接口的类型并且被net 库支持的类型 包括:TCPAddr、UDPAddr、IPAddr。

    下面通过代码演示如何指定client 使用的IP和端口号。

    例子中使用TCPAddr 类型。

    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 main() {
    
    	serverAddr := "172.20.22.160:8080"
    
    	// 172.28.0.180
    	//localIP := []byte{0xAC, 0x1C, 0, 0xB4}  // 指定IP
    	localIP := []byte{} //  any IP,不指定IP
    	localPort := 9001   // 指定端口
    	conn, err := DialCustom("tcp", serverAddr, time.Second*10, localIP,localPort)
    	if err != nil {
    		fmt.Println("dial failed:", err)
    		os.Exit(1)
    	}
    	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))
    
    	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")
    
    }
    
    
    
    

    测试

    启动client,只指定端口

    $ ./client 
    netAddr: :9001
    count: 28 msg: You are welcome. I'm server.
    

    启动client,指定IP,Port

    $ ./client
    netAddr: 172.28.172.180:9001
    count: 28 msg: You are welcome. I'm server
    

    server输出

    ./sever
    2018/06/19 18:15:41 rpc listening 0.0.0.0:8080
    send: 28
    connetion end
    

    查看连接

    $ netstat -anp | grep 8080
    tcp        0      0 :::8080                     :::*                        LISTEN      27328/./server      
    tcp        0      0 ::ffff:172.20.22.160:8080   ::ffff:172.28.0.180:9001  ESTABLISHED 27328/./server   
    

    从测试结果看,可以成功指定IP和端口。

  • 相关阅读:
    Spring模板方法模式及Callback
    vc新线程、类外控制EDIT控件
    OpenGL绘制框架
    回调函数c++
    matlab练习程序(求灰度图像最大灰度,最小灰度,平均灰度)
    OpenGL绘制函数
    matlab练习程序(图像傅里叶变换,幅度谱,相位谱)
    多项式系数提取算法 c++
    OpenGL绘制复杂图形
    matlab练习程序(图像加噪,各种滤波)
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/9202331.html
Copyright © 2020-2023  润新知