在Linux当中,我们知道,每一个进程都有自己唯一的PID。而这个唯一的PID可以标识一个主机当中的唯一一个进程,今天在用modbus写通信期间遇见一个很有意思的问题。

        说是有意思讲来简单,就是简单的端口占用问题,我们知道modbus是应用层的协议,但是是基于传输层的TCP协议来实现的。这就导致一个问题,当客户端连接服务器后,服务器意外终止了,此时端口会进入一个被占用的状态,服务器会等待一端时间后才会释放端口。

        这里我查了一下,一个端口能被多个进程使用的情况,按道理来说这个是行不通的,但是这个实现其实是,一个端口上可以运行许多个进程,每个进程都可以调用同一个端口,但是当有一个进程在占用该端口时,其他进程会等待,等前一个进程释放该端口后才可以由下一个进程调用。问题就出在占用问题之上。只要程序不是一直占用这个端口,这就可以重复使用这个端口。

        但是这个还是有一些问题的,真正的解决方案就是端口复用

        用的是setsockopt函数,设置应用层,启用端口复用函数来实现,端口复用的使用是有一些注意的,受限端口的绑定得要在read,write函数之前进行绑定,因为在发送信息函数( sendto, 或 write ),系统会自动给当前网络程序分配一个随机端口号,这相当于随机绑定了一个端口号,这里只会分配一次,以后通信就以这个随机端口通信,我们再绑定端口号的话,就会绑定失败。如果我们放在发送信息函数( sendto, 或 write )之前绑定,那样程序将以我们绑定的端口号发送信息,不会再随机分配一个端口号。所以端口复用函数要在绑定之后进行。

SO_REUSEADDR可以用在以下四种情况下。 (摘自《Unix网络编程》卷一,即UNPv1)

1、当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。

2、SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。

3、SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。

4、SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。

需要注意的是,设置端口复用函数要在绑定之前调用,而且只要绑定到同一个端口的所有套接字都得设置复用

        端口复用允许在一个应用程序可以把 n 个套接字绑在一个端口上而不出错。同时,这 n 个套接字发送信息都正常,没有问题。但是,这些套接字并不是所有都能读取信息。这就涉及到复用当中的一些问题,

        绑定时都可以绑定的,但是在接受消息方面又其他的结论:

        

1.如果两个进程都绑定的是本地的真实ip,如 ip addr.sin_addr.S_un.S_addr = inet_addr("10.110.12.68");

那谁先绑定谁就可以收到数据。后面虽然可以绑定,但是收不到发送过来的数据。

2.如果两个进程一个绑定的是INADDR_ANY,而一个绑定的是真实ip,那么最终收到数据的是真实ip,如果两者都是绑定的真是ip,在Linux当中就时后绑定的可以接受数据。

        具体可以看:原文链接:https://blog.csdn.net/zhanghuaichao/article/details/105122969

相关阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。