Misunderstanding of the maximum number of connections "65535"

programming model

Let's take a look at the programming model of socket first: the

above picture is from this article

Different from the C language, the go language helps us encapsulate the socket at the bottom layer. When ListenTCP creates, binds, and listens; when DialTCP, creates and connects. For details, see this article , or trace it in debug mode. Let's use the code to clear the myth that the server can only have 65536 maximum links.

server code

server.go

package main

import (
    "fmt"
    "net"
    "os"
)

func main() {
    if len(os.Args) != 2 {
        fmt.Printf("Usage: %s host:port\n", os.Args[0])
        return
    }

    //创建TCP协议
    tcpAddr, err := net.ResolveTCPAddr("tcp4", os.Args[1]) //tcp4 是协议版本,还有tcp6 如果只有端口的话默认绑定127.0.0.1
    checkError(err)

    //创建、绑定、监听socket
    listener, err := net.ListenTCP("tcp4", tcpAddr)
    checkError(err)
    for {
        //等待连接
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        //处理连接
        go handleClient(conn)
    }
}

func handleClient(conn net.Conn) {
    defer conn.Close()
    fmt.Printf("client address %s\n",conn.RemoteAddr().String())
    conn.Write([]byte(`hello`))
}

func checkError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s\n", err.Error())
        os.Exit(1)
    }
}

client code

package main

import (
    "fmt"
    "net"
    "os"
    "time"
)

func main() {
    if len(os.Args) != 2 {
        fmt.Print( "Usage: %s host:port \n", os.Args[0])
        return
    }

    tcpAddr, err := net.ResolveTCPAddr("tcp4", os.Args[1])
    checkError(err)
    //创建socket并连接服务器
    conn, err := net.DialTCP("tcp4", nil, tcpAddr)
    checkError(err)
    fmt.Printf("client address %s\n",conn.LocalAddr().String())

    defer conn.Close()
    var buf [512]byte
    for {
        //从服务器读取数据
        n, err := conn.Read(buf[0:])
        if n == 0 {
            time.Sleep(time.Second)  //如果没读到就继续等待
            continue
        }
        checkError(err)
        fmt.Printf("receive %s from server\n",string(buf[0:n]))

    }


}
func checkError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s\n", err.Error())
        os.Exit(1)
    }
}

test link

Two computers are required for testing, here a virtual machine is used

Start the server

go run server.go 0.0.0.0:7777 , here runs the server on a virtual machine
Here 0.0.0.0 means to allow links from outside

start the client

go run client.go server ip address: 7777, where the client is run locally and four are started

view port

Server

client

From the above figure we can see:

  • After the client connects to the server, the server randomly assigns a port to the client, and the client binds and assigns its own port.
  • For the client, the port 7777 is not bound, otherwise we will not be able to start multiple clients. For the client, the port 7777 is the coordinate for connecting to the server.
  • Looking at the server, after the connection is established after being assigned to the client, the assigned port is not bound, such as 43718 in the figure above.

Where does misunderstanding come from

Looking at the programming model of socket, I estimate that it is in the link of accept with the server. In fact, this link does not bind another port to communicate with the client.
To expand, in fact, for the server, the number of ports cannot be limited (because only one port is bound), then the total number of connected clients is limited by memory, CPU and network bandwidth.
For the client, when connecting to the same server, one port is occupied. For the same computer, the total number of clients that can be run is limited by the number of ports, memory, CPU and network bandwidth.
In addition, the number of 65535 can actually be changed.

Recommended tools

The virtual machine here uses vagrant, a convenient virtual machine management software,

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325093500&siteId=291194637