Golang Go语言中如何在同一个端口上建立不同的连接?

根据四元组,一个连接对应一个连接型 socket 应该是可行的 连接 a local:12301->local:689 连接 b local:12301->local:8080


Golang Go语言中如何在同一个端口上建立不同的连接?
20 回复

On TCP 的链接是你应用的概念。你直接自定义一套报文结构不就行了

更多关于Golang Go语言中如何在同一个端口上建立不同的连接?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你想用来干啥。。

想不通。

没明白 OP 的问题是什么?服务端监听 80 端口,有两个客户端,分别是 123->80 | 124->80 ,这完全没有问题啊

网页端的正文按 ctrl+enter 居然是直接发送无法换行 什么 nt 设定。。。。
go <br> <br> host0 := "remote"<br> port0 := "8080"<br><br> host1 := "remote"<br> port1 := "689"<br><br> // 本机端口<br> localPort := "12301"<br><br> // 创建本机地址<br> localAddr, err := net.ResolveTCPAddr("tcp", "localhost:"+localPort)<br> if err != nil {<br> fmt.Println("Error resolving local address:", err)<br> os.Exit(1)<br> }<br><br> // 创建远程地址 8080<br> remoteAddr0, err := net.ResolveTCPAddr("tcp", host0+":"+port0)<br> if err != nil {<br> fmt.Println("Error resolving remote address:", err)<br> os.Exit(1)<br> }<br> // 创建远程地址 689<br> remoteAddr1, err := net.ResolveTCPAddr("tcp", host1+":"+port1)<br> if err != nil {<br> fmt.Println("Error resolving remote address:", err)<br> os.Exit(1)<br> }<br> // 建立连接<br> go dial(localAddr, remoteAddr0)<br> dial(localAddr, remoteAddr1)<br>
go<br> func dial(l, r *net.TCPAddr) {<br> localConn, err := net.DialTCP("tcp", l, r)<br> if err != nil {<br> fmt.Println("Error connecting to remote host:", err)<br> os.Exit(1)<br> }<br> localConn.Write([]byte("ping"))<br>}<br>
bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.

我想用本机上的同一个端口去连接不同的服务器,但这个好像在 netty 上可以实现,不知道在 go 上如何实现,go 在 dialTcp 的时候,将 socket bind 了端口

natmap https://github.com/heiher/natmap 似乎就能实现类似效果
可以问一下作者 相关细节

Control 里把 SO_REUSEPORT 设置上

在 Linux 上可以直接创建多个 TCP socket 绑定同一个端口来连接至多个不同的目的地址:端口,也不需要开启 reuseport 。但如果该端口已经被某个 socket 绑定并且处于 listen 状态则不行。

自定义一个报头,标记两种不同流量

我看是在 Go 板块的贴,对于 Go 说那就是 go-reuseport 。

一些操作系统比如 Windows ,两个 socket 中一个绑定「 0.0.0.0:12301 」另一个绑定「本机 IP:12301 」,不需要其他的操作就能满足你的要求。

突然发现之前啃了好久的 bind 和 connect 在处理这个本地端口上的逻辑全忘光了……

bind 之前开启 SO_REUSEADDR 选项(注意不是 SO_REUSEPORT )

这个是 Linux 的特性,Linux 在 bind 本地端口时默认采用三元组(协议、源地址、源端口)判断冲突,有冲突即不能 bind (错误信息为 address already in use ,注意这个错误信息,暗示了后面应该开启什么选项)。

同时,在 socket 上提供了一个 SO_REUSEADDR 的选项,开启之后可以绕过这个 bind 时期的三元组检查。(由于 TCP/IP 协议本身的特性,仍然需要保证五元组不能冲突,否则后续的 connect 或 listen 操作仍然会出错)

注意 SO_REUSEPORT 选项是另外一个用途,和这个问题无关。

ctrl+enter = 发送
这是早期聊天软件(包括 QQ )的习惯,接触互联网足够早的话,会对这个快捷键很熟悉

V 站网页版编辑框换行的话,直接按 Enter 就行了,不需要加什么 CTRL SHIFT 之类的

reuse 只能多个进程 read 同一个 socket ,bind 也只能绑定一个地址,不然就违反了五元组的限制。可以用 UDP 或 IPConn 的 WriteTo 实现对多通信

UDP 就可以啊

你是想实现流量中转?

设置 SO_REUSEPORT 就可以了,参考我开源的单机百万实时通讯服务(自研消息 DB ,二进制协议,重写 go 底层 epoll 网络)
https://github.com/WuKongIM/WuKongIM

在Golang(Go语言)中,通常一个端口只能绑定到一个监听套接字(socket)上,但你可以通过在该套接字上接受多个连接来实现多个客户端的同时连接。这是通过多路复用(multiplexing)技术实现的,最常用的方式是使用Go的net包中的net.Listenernet.Conn接口。

要在同一个端口上处理不同的连接,你可以遵循以下步骤:

  1. 创建监听器:使用net.Listen函数在指定端口上创建一个监听器。例如,ln, err := net.Listen("tcp", ":8080")

  2. 接受连接:使用ln.Accept()在一个无限循环中接受新的连接。每次调用Accept都会阻塞,直到一个新的连接建立,然后返回一个net.Conn对象。

  3. 处理连接:为每个新的连接启动一个新的goroutine,这样主goroutine可以继续接受新的连接。在新的goroutine中,你可以使用net.ConnReadWrite方法读取和写入数据。

  4. 关闭连接:在数据交换完成后,确保关闭连接以释放资源。

示例代码:

ln, err := net.Listen("tcp", ":8080")
if err != nil {
    log.Fatal(err)
}
defer ln.Close()
for {
    conn, err := ln.Accept()
    if err != nil {
        log.Println(err)
        continue
    }
    go handleConnection(conn)
}

这种方式允许你在同一个端口上处理多个并发连接,是Go语言并发编程优势的体现。

回到顶部