如何在同一个端口上建立不同的连接?

2023-07-19 19:35:14 +08:00
 voidmnwzp

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

2585 次点击
所在节点    Go 编程语言
20 条回复
ManjusakaL
2023-07-19 19:38:15 +08:00
On TCP 的链接是你应用的概念。你直接自定义一套报文结构不就行了
flyqie
2023-07-19 19:39:24 +08:00
你想用来干啥。。

想不通。
xuanbg
2023-07-19 19:41:07 +08:00
没明白 OP 的问题是什么?服务端监听 80 端口,有两个客户端,分别是 123->80 | 124->80 ,这完全没有问题啊
voidmnwzp
2023-07-19 20:01:08 +08:00
网页端的正文按 ctrl+enter 居然是直接发送无法换行 什么 nt 设定。。。。
``` go

host0 := "remote"
port0 := "8080"

host1 := "remote"
port1 := "689"

// 本机端口
localPort := "12301"

// 创建本机地址
localAddr, err := net.ResolveTCPAddr("tcp", "localhost:"+localPort)
if err != nil {
fmt.Println("Error resolving local address:", err)
os.Exit(1)
}

// 创建远程地址 8080
remoteAddr0, err := net.ResolveTCPAddr("tcp", host0+":"+port0)
if err != nil {
fmt.Println("Error resolving remote address:", err)
os.Exit(1)
}
// 创建远程地址 689
remoteAddr1, err := net.ResolveTCPAddr("tcp", host1+":"+port1)
if err != nil {
fmt.Println("Error resolving remote address:", err)
os.Exit(1)
}
// 建立连接
go dial(localAddr, remoteAddr0)
dial(localAddr, remoteAddr1)
```
``` go
func dial(l, r *net.TCPAddr) {
localConn, err := net.DialTCP("tcp", l, r)
if err != nil {
fmt.Println("Error connecting to remote host:", err)
os.Exit(1)
}
localConn.Write([]byte("ping"))
}
```
bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.

我想用本机上的同一个端口去连接不同的服务器,但这个好像在 netty 上可以实现,不知道在 go 上如何实现,go 在 dialTcp 的时候,将 socket bind 了端口
voidmnwzp
2023-07-19 20:01:44 +08:00
ysc3839
2023-07-19 20:10:27 +08:00
natmap https://github.com/heiher/natmap 似乎就能实现类似效果
可以问一下作者 @heiher 相关细节
leonshaw
2023-07-19 20:15:02 +08:00
Control 里把 SO_REUSEPORT 设置上
gps949
2023-07-19 20:24:02 +08:00
heiher
2023-07-19 22:13:07 +08:00
在 Linux 上可以直接创建多个 TCP socket 绑定同一个端口来连接至多个不同的目的地址:端口,也不需要开启 reuseport 。但如果该端口已经被某个 socket 绑定并且处于 listen 状态则不行。
zachary99
2023-07-19 22:35:15 +08:00
自定义一个报头,标记两种不同流量
mikewang
2023-07-19 22:42:23 +08:00
我看是在 Go 板块的贴,对于 Go 说那就是 go-reuseport 。

一些操作系统比如 Windows ,两个 socket 中一个绑定「 0.0.0.0:12301 」另一个绑定「本机 IP:12301 」,不需要其他的操作就能满足你的要求。
rrfeng
2023-07-19 22:54:00 +08:00
突然发现之前啃了好久的 bind 和 connect 在处理这个本地端口上的逻辑全忘光了……
qbqbqbqb
2023-07-20 01:29:35 +08:00
bind 之前开启 SO_REUSEADDR 选项(注意不是 SO_REUSEPORT )
qbqbqbqb
2023-07-20 01:36:26 +08:00
这个是 Linux 的特性,Linux 在 bind 本地端口时默认采用三元组(协议、源地址、源端口)判断冲突,有冲突即不能 bind (错误信息为 address already in use ,注意这个错误信息,暗示了后面应该开启什么选项)。

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

注意 SO_REUSEPORT 选项是另外一个用途,和这个问题无关。
cnbatch
2023-07-20 02:29:32 +08:00
ctrl+enter = 发送
这是早期聊天软件(包括 QQ )的习惯,接触互联网足够早的话,会对这个快捷键很熟悉

V 站网页版编辑框换行的话,直接按 Enter 就行了,不需要加什么 CTRL SHIFT 之类的
lysS
2023-07-20 09:12:52 +08:00
@leonshaw reuse 只能多个进程 read 同一个 socket ,bind 也只能绑定一个地址,不然就违反了五元组的限制。可以用 UDP 或 IPConn 的 WriteTo 实现对多通信
daokedao
2023-07-20 09:14:37 +08:00
UDP 就可以啊
Goooooos
2023-07-20 09:21:21 +08:00
你是想实现流量中转?
leonshaw
2023-07-20 10:17:44 +08:00
@lysS 这个讲的比较清楚: https://stackoverflow.com/a/14388707
wkong
2023-07-25 10:56:29 +08:00
设置 SO_REUSEPORT 就可以了,参考我开源的单机百万实时通讯服务(自研消息 DB ,二进制协议,重写 go 底层 epoll 网络)
https://github.com/WuKongIM/WuKongIM

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/958100

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX