多线程下socket的bind、accept函数分析以及对socket端口号的深入理解

本文原创,欢迎转载,转载时请注明出处,谢谢:https://blog.csdn.net/zz420521/article/details/81914358

我们知道,在TCP协议下的网络通讯,服务器在accept之后会生成一个新的套接字与客户端进行通讯,这个新套接字的端口是提供给客户端的,所以是属于客户端的端口,等下有试验证明。

一般来说,服务器accept返回的这个新套接字的端口号是操作系统随机分配的, 在分配的时候, 操作系统会保证不与现有的端口冲突。当然这个端口也可以通过客户端程序那边的客户端socket也执行bind来实现端口定死,但这通常是没有必要的,而且容易出问题,所以客户端程序那边的客户端套接字是没有必要调用bind函数的。

https://blog.csdn.net/stpeace/article/details/45001255  这篇博文中有详细解释,为何客户端不需要bind客户端自身的端口号。

 

在多线程下,现在如果有两个线程分别connect服务器,那么服务器accpet两次,自然会各分配出一个未使用的(不会与现有端口冲出,包括listen监听口)端口号,分别与客户端通讯,且这两个端口不相同。

那么问题来了,客户端的两个线程确实是由服务器那边提供了两个不同的端口(再次强调,新的两个端口确实是服务器分配的,但是是给客户端用的,所以是属于客户端的两个端口。这是我的理解,等下做实验,如果有问题,请留言讨论),但是服务器这边只有一个端口啊,那证客户端的两个两个线程的端口对服务器的同一个端口的访问不是就产生竞争了吗?会不会产生乱序的情况呢?

经过做实验,这种情况是不会产生的。先上实验结果:

实验的思想过程是:客户端开两个线程,每个线程的代码基本一样,只不过线程2比线程1晚开始5秒钟,还有就是cout的输入内容区分了是线程1还是线程2,其他的完全一样。服务器也两个线程,分别与客户端的两个线程对应。每accept成功一次,服务器端就生成一个线程,总共两个。

客户端程序代码中的一段:属于线程1,线程2同理。用于标记连接后的客户端的端口和服务器的端口各是多少。

服务器程序代码中的一段:用来显示服务器accept两个服务器线程1、2的过程。

实验结果:

直接上图,结论:

1. 首先客户端的线程一和服务端的线程一执行,每隔一秒交换一次数据。经过5秒,客户端的线程二和和服务器的线程二进行通讯,每隔两秒交换一次数据,所以可以从图上看出,线程1发送数据的频率是线程2发送数据的频率的两倍。而且经过长时间的测试,输出结果的顺序不会发生错位,也就是说,各自对应的socket都正常的各搞各的,相互不受任何影响。

2. 客户端的两个线程所连接的服务器端口号都为16415(在客户端程序里面,通过getpeername函数返回,表示的是通讯对端的端口号,也就是服务器的端口号,见第一张图)。这个是网络端口号,对应的主机端口号是8000,正好是我客户端程序里面设定的服务器端口号。所以说,服务器的监听端口号、accept之后建立的两个线程与客户端通讯时的服务器端口号都是8000!!!

3. 客户端的两个线程各自的客户端端口号是由服务器给分配的,且不重复的端口号(上图实际上显示的是主机号,要转换成端口号还是需要调用ntohl函数。我没有作明显区分端口号和主机号,只是为了说明端口号不同),一个是52966,一个是53222(在客户端程序里面,通过getsockname函数返回,表示的是通讯本机的端口号,见第一张图)。所以说,我认为服务器确实通过accept分配了未占用的端口号,但是这个端口号提供给了客户端,通过客户端程序的getsockname函数可得,所以是属于客户端的端口号。

那么,为什么用两个线程访问同一个端口不出问题呢?这是因为,socket这个东西跟文件句柄很相似,实际上,在BSD系统里就是跟文件句柄一样存放在一样的进程句柄里。这个socket其实是一个序号,表示其在句柄表中的位置。socket跟TCP/IP并没有必然的联系。如果一个程序创建了一个socket,并让其监

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值