当前位置:C++技术网 > 精选软件 > 关于Socket编程监听端口是否指定IP的思考

关于Socket编程监听端口是否指定IP的思考

更新时间:2016-10-10 17:51:02浏览次数:1+次

    在文章《自动获取IP提高易用性含C++获取本机IP获取本机局域网IP的代码实现》中,我已经总结了简便实用和灵活设置的软件开发权衡的一些经验。本文进一步对Socket编程的服务器端监听端口和IP做一个讨论。
    不管是做什么软件,总是为了业务而生的。这里说的业务也就是实际的使用场景。可以是自己做的一个小小的实用工具,也可以是公司业务。不管是什么,根本点就是实际的使用场景。要做好业务,也就是要贴近实际的使用场景来思考软件如何开发。这样你做的软件才会得到用户的青睐。
    当然,我们不仅要考虑到用户的喜爱,还要考虑到自己实现的方便性。如果一味追求用户喜爱而让实现异常艰难,也使今后的维护成本太高,软件也就难以发展。

    我们这里就探讨一下Socket编程监听端口是否指定IP的问题。

关于Socket编程监听端口是否指定IP的思考

    我们在学习Socket编程的时候,知道TCP服务器端需要监听端口。监听需要指定对应的IP和端口。这些是编程常识了。而一个计算机中,会有多个IP。最基本的就是本机回环测试IP即127.0.0.1。这个IP地址仅用作本机使用,用于网络程序开发时本机测试,而不需要动用其他计算机来测试开发。这样本机IP显得非常方便。服务端程序和客户端程序都运行在一个计算机中,而且可以是同时处于调试状态,这样我们可以方便的联合调试服务器端和客户端程序。这样可以大大提高开发调试效率。而平时运行一些无需与外网通信的网络程序的时候,我们也可以用本机IP地址来为其他程序提供服务,而且提供的方式就是IP方式,而不是主机名方式。此时如果我们想让提供给127.0.0.1的服务变成真正的网络程序,我们只需要提供网卡支持即可。
    有了网卡,我们的计算机就可以与其他计算机通信了。因此也就有了通向外部网络的出口了。而第一步通过的一般都是局域网。计算机接入局域网后,就会和局域网里的计算机打成一片。而相互通信的依据就是计算机的局域网IP。所以,只要计算机处于一个局域网中,就会有这个局域网的IP。否则,也无法叫做处在一个局域网中。
    一般情况下,一台计算机只有一个网卡。一个网卡也就对应一个IP。IP是计算机在网络的唯一标识。当然,这个IP也是可以变的。但是在某一刻,你只能拥有一个IP。如果你经常变动IP,也就和你经常换手机号一样。换了之后,其他计算机就找不到你了。
    当然,网卡只是一个设备而已,我们的计算机都可以接入多个网卡。这样一来,我们的计算机实际上就可以同时拥有多个IP。我想你也可能同时拥有过两个手机号吧,是一个道理。
    而多个网卡是硬件,对于程序来讲,只是多了一个可以与外界通信的出口而已。所以在使用的时候,也就多了一个选择。但是不管如何选择,一次通信只能有一个固定的IP。
    那么公网IP是怎么回事呢?公网IP是一种非常稀缺的资源,不像局域网IP。我们可以随时组件一个局域网,也可以随时更换局域网IP。然而公网指的是全球互联网,全球计算机都被连在一起,全球的计算机如果需要相互通信,就需要公网IP。公网IP的获取是需要经济支持的。所谓的网费,实际上一大部分是用于支付IP使用费,然后就是基础设施使用费用等。
    除了本机IP127.0.0.1,其他IP都是第三方分配的。也就是说,你的计算机的局域网IP并不是你想设置成什么就是什么的,而是局域网IP管理处分配给你哪个可以用,你才可以设置成这个IP,否则无法和其他局域网计算机通信。同理,公网IP也是如此。因为局域网IP范围很小,随时可以组建一个,并不是什么稀缺资源,所以不要钱。而公网是互联网,组建好后,就固定下来了。而且,公网不是随便说组建就可以的,需要大量的基础通信设施做基础的。
    如果你得到了一个公网IP,那么你的计算机就同时可以拥有了本机IP、多个局域网IP(多网卡支持)和公网IP。此时你获取计算机的IP时,你会发现有很多个。
    在做Socket编程时,TCP服务器端程序会先监听端口,同时也会指定本机的IP。这个IP也就是计算机拥有的众多IP中的一个。为了简便,我们经常不关注本机的IP,所以就使用了宏INADDR_ANY作为监听的IP。而宏INADDR_ANY定义为0.0.0.0,表示的是不确定的IP地址,或者说是本机拥有的任意IP地址,这表示你只关心监听的端口。
    设置为INADDR_ANY,程序监听本机拥有的所有IP对应的端口,并从端口提取需要的数据处理。如果你不清楚本机的IP,或者也不确定本机的IP,这样就挺好。我想,我们一开始学习TCP编程的时候,基本上都是用了INADDR_ANY。然而在实际开发场景中,就不能这么随便设置了。我们需要充分考虑使用的场景来确定。
    如果我们的TCP服务端程序运行于公网IP环境下,一般就是服务器上。此时我们一般对外就是提供公网IP。这个IP是固定的,已知的。而我们的程序只对端口感兴趣,对IP没有兴趣。此时,为了方便,你可以使用INADDR_ANY。因此此时客户端是知道使用公网IP连接你这个服务器程序的。
    而我做的这个服务器程序并不是运行于公网之上的,而是运行于局域网中的。在局域网中,我们的IP一般情况都是动态分配的,除非你以固定方式分配。但是我们无法保证人家局域网的IP分配规则。同时,因为我们是服务器端程序,在局域网中,我们必须让客户端知道我们是哪个局域网IP,否则客户端就无法连接过来了。而且,假如你的计算机拥有多个网卡(这个很常见,基本是主板都集成了网卡,你可能还会安装无线网卡等),这样你的计算机是有多个局域网IP的,加上IP分配是动态的。假如此时你使用INADDR_ANY,表示你不关心IP。虽然你是可以正常监听对应的端口,然而,却没有人找得到你这个服务器。服务器是图省心了,就真省心了,因为客户端就找不到你了。服务器就可以睡大觉了。
    而当你在回头去查询TCP服务器监听的IP时,是0.0.0.0。你说这个地址让客户端怎么连接呢?
    所以在做局域网的TCP服务器端程序的时候,IP必须要显式指定。也就是绑定IP和端口的时候,IP不能是INADDR_ANY。你可以随意在多个IP中选择一个,但是不能随意到都不选。否则的话,你得特地告知客户端你的局域网IP是多少。那不是变得更加麻烦了。很多电脑用户连查看IP都不知道。为了不明确指定IP地址或者叫做偷懒,结果让使用非常麻烦。这不是一个好的软件应该做的事情。
    我们应该做的就是,使用明确的局域网IP,并在软件中显示出来。而不是让用户去动电脑去查看IP。而我们使用公网IP的时候,毕竟公网IP一般属于长期使用的,不会变,所以可以告诉客户端使用公网IP连接,而局域网IP更新周期可能很快,或者不稳定。服务器端程序重启或者服务器电脑重启或者局域网IP更新时间到了,局域网IP也就变了。毕竟局域网IP是免费的,人家不会为你负责的。
    最后总结一下,Socket编程监听端口是否指定IP的基本参考原则就是,如果你可以方便的告知客户端你的IP或者告知的代价很低或者长期可以稳定使用,那么你可以使用INADDR_ANY设置TCP绑定的IP和监听的端口。如果不是,那么请明确指定绑定的IP和监听的端口。