聊一聊服务器和客户端会话过程中的端口

时间:2024-04-07 11:52:25

之前在TCP/IP的网络通信的学习中,主要关注的都是高并发,高性能的方面,忽略了一些基本的概念,特别是端口这个东西,这个东西在服务器开发过程中可能看起来也不是很麻烦,在服务器上就是一个bind(),在客户端指定一下目标端口就行了,也没有太深入理解其中的东西,今天就来好好的总结梳理一下。

还是以服务器和客户端的会话为例,什么是端口呢?如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口 可以有65536(即:256×256)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(256×256-1)。端口其实就是队,操作系统为各个进程分配了不同的队,数据包按照目的端口被推入相应的队中,等待被进程取用,在极特殊的情况下,这个队也是有可能溢出的,不过操作系统允许各进程指定和调整自己的队的大小。一个数据包包括了文件,ip,和端口号,ip是为了服务器可以找到你的主机,端口号是你接受数据包的门户, 而所谓的端口监听,是指主机网络进程接受到IP数据包后,察看其的目标端口是不是自己的端口号,如果是的话就接受该数据包进行处理。


在服务器和客户端通信过程中,socket通信的双方自己决定自己要用什么端口,服务器端只能决定自己listen的是哪个端口,不能决定客户端的端口;客户端也只能决定自己的端口,当然,因为它是主动连接的,所以它知道对方的端口号,但它也不能把对方的服务移到别的端口上面去。端口号是用来区分相同主机上的不同socket的,它相当于socket在本机这一端的名字,一个端口只能bind一次,占用了之后同时就不能再给别人用了,这么宝贵的资源都要留给listen的一方,主动连接的一方一般去用那些操作系统随机分配的端口号。bind也可以指定端口号为0,这种情况下就是随机绑定一个没有使用过的端口号,可以用来在建立连接之前就确定本端的端口号。作为listen的一方,所有被动建立起来的连接的本端端口都是listen的端口。只有源IP、源端口、目的IP、目的端口还有协议号都完全相同才会认为是同一个socket,所以被动建立连接的socket源端口号不同,目的端口号是可以相同的。

我们在linux环境来查看一下端口使用情况:

输入命令netstat -tunap(-t 表示显示tcp相关 -u表示显示udp相关 -n表示拒绝显示别名,能显示数字全部转换为数字 -a表示显示所有状态的,-l则表示显示listen状态的 不输入则表示显示established状态的 -p表示显示建立相关链接的程序名),效果如下

聊一聊服务器和客户端会话过程中的端口

在ip地址后的冒号,如这个聊一聊服务器和客户端会话过程中的端口,0.0.0.0表示ip,表示111端口号。

什么时候需要使用到端口这个东西呢?

1、采用TCP通信时,客户端不需要bind()他自己的IP和端口号,而服务器必须要bind()自己本机的IP和端口号;

2、若采用UDP通信时(这里是有客户端和服务器之分才这么说的,若是指定特定端口的UDP对等通信则不一样了),客户端也可以不需要bind()他自己的IP和端口号,而服务器需要bind自己IP地址和端口号;

再说下客户端用不用bind的区别

无连接的socket的客户和服务以及面向连接socket的服务通过调用bind函数来配置本地信息。使用bind函数时,通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。
  Bind()函数在成功被调用时返回0;出现错误时返回"-1"并将errno置为相应的错误号。需要注意的是,在调用bind函数时一般不要将端口号置为小于1024的值,因为1到1024是保留端口号,你可以选择大于1024中的任何一个没有被占用的端口号。

 有连接的socket客户通过调用Connect函数socket数据结构中保存本地和远信息无须调用bind(),因为这种情况下只需知道目的机器的IP地址,而客户通过哪个端口与服务器建立连接并不需要关心,socket执行体为你的程序自动选择一个未被占用的端口,并通知你的程序数据什么时候打开端口。(当然也有特殊情况,linux系统中rlogin命令应当调用bind函数绑定一个未用的保留端口号,还有当客户需要用指定的网络设备接口和端口号进行通信等等)
总之:
1.需要在建连前就知道端口的话,需要 bind 
2.需要通过指定的端口来通讯的话,需要 bind


再说一个问题,为什么你用浏览器打开一个网站不需要输入端口呢不是说好客户端访问服务器需要指定端口号的吗?其实,是你的浏览器默认帮助你的ip地址后面加上了:80,80端口是默认的http端口,所以就不需要你输入网址时加端口啦,如果你自己搭建了一个服务器,比如nginx,你把config文件里的listen端口改成其他端口,你看你的浏览器还是否能够不加端口访问。