我正在使用C和编写客户端服务器程序,我想获得一个未使用的端口号来运行我的服务器进程。 我的服务器代码是这样的:
getaddrinfo() socket() bind() listen while(1) accept()
我需要将未使用的端口地址提供给bind()调用。 但是我不想在启动服务器进程时通过命令行传递端口号。 端口号应该通过套接字调用获得,我需要使用它来启动我的客户端进程。 有没有任何套接字调用,可以帮助我在C中dynamic获取未使用的端口?
只需将sockaddr_in中的套接字设置sin_port绑定到0即可。 系统会自动选择未使用的端口。 你可以通过调用getsockname()来获取它。
但我不知道如何将它传递给客户端,除了打印它并使用客户端程序的命令行参数。
这将是一个巨大的竞争条件 。 想象一下这一系列事件:
getNextFreePort()
调用。 bind()
,这与“使用中的地址”失败。 这就是服务器倾向于拥有“知名”地址的原因,因为这是为了使客户端知道应该连接的位置。
另外,除非我误会,否则您似乎期望客户端能够在启动时调用getNextFreePort()
,然后奇迹般地获取服务器已经获得的端口号并使用? 这没有什么意义,所以希望我误解了你。
由于你在Linux / Unix上,这正是RPC portmapper设计要解决的问题。 您的服务器bind()
到一个未使用的端口(端口0),然后通过应用程序/服务名称将由此生成的实际端口(通过getsockname()
与portmapper进行注册。
然后,客户端在其已知端口上查询portmapper,询问实际运行了哪个名称服务的端口。
portmapper RPC不像以前那样受欢迎
如果服务器和客户机在同一个机器上:
另一种方法是使用某种共享文件的命名方式(创建一个临时文件/tmp/servport.xxxxx),将xxxxx替换为该端口。
或者你可以创建一个共享内存段,服务器将其端口插入。 客户端将连接到相同的共享内存,读取端口,并正常连接。
或者你的服务器可以在已知/共享路径上创建一个unix域套接字,客户端可以连接到这个套接字,询问服务器在哪个端口上。 (显然,如果他们都是本地的,你可以这样做所有的IPC!)
很多IPC的选择…
如果将()绑定到一个随机或不可预知的地址+端口号,客户端可能会遇到一些困难,找到您的服务器并连接到它。