手把手写C++服务器(12):TCP自连接原理Python示例解决方案

Posted 沉迷单车的追风少年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手写C++服务器(12):TCP自连接原理Python示例解决方案相关的知识,希望对你有一定的参考价值。

前言:《手把手写C++服务器》系列的第一篇文章:手把手写C++服务器(1):网络编程常见误区,当中就讲解了TCP自连接是网络编程常见的误区之一。这篇blog进一步讨论TCP自连接问题,并给出Python实例代码,以及这类问题的解决方案。

目录

什么是TCP自连接问题?

为什么说是坑?

TCP自连接带来的危害?

选择端口的范围

查看端口号

如何解决TCP自连接问题?

Python3程序示例

参考


什么是TCP自连接问题?

自连接就是自己连接自己的现象。当我们去连接一个正在监听的端口时,系统自动为我们分配一个临时端口去进行连接,这样就有可能分配到正在监听的端口号,然后出现自己连接自己的问题。

为什么说是坑?

因为当没意识到出现TCP自连接的时候,很难找到端口被占用的真正原因,给问题定位带来困难。具体的解决方法很简单。

TCP自连接带来的危害?

当程序去connect一个不处于监听的端口时,必然期待其连接失败,如果自连接出现,就意味着该端口被占用了,那么:

  •     真正需要监听该端口的服务会启动失败,抛出端口已被占用的异常。
  •     客户端无法正常完成数据通信,因为这是个自连接,并不是一个正常的服务。

选择端口的范围

使用命令: sysctl -A |grep local_port_range

sysctl -A |grep local_port_range
sysctl: reading key "kernel.unprivileged_userns_apparmor_policy"
net.ipv4.ip_local_port_range = 32768    60999
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.eth0.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"

端口号的范围是32768到60999之间

查看端口号

使用命令:nestat -ln

可以看到部署服务器的时候,为了安全仅仅开放了一个端口号22

如何解决TCP自连接问题?

断开连接重试即可。

Python3程序示例

#!/usr/bin/python3

import errno
import socket
import sys
import time

if len(sys.argv) < 2:
    print("Usage: %s port" % sys.argv[0])
    print("port should in net.ipv4.ip_local_port_range")
else:
    port = int(sys.argv[1])
    for i in range(65536):
        try:
            sock = socket.create_connection(('localhost', port))
            print("connected", sock.getsockname(), sock.getpeername())
            time.sleep(60*60)
        except socket.error as e:
            if e.errno != errno.ECONNREFUSED:
                print("socket error!")
                break
print("end!")

运行后,TCP在net.ipv4.ip_local_port_range范围内选择一个端口号连接服务器端口,如果这时候我们指定的端口号正好和自身的端口号相连就会出现TCP自连接问题了。

运行命令:

python self-connect-python3.py 22

我们这里会不会出现自连接问题呢?

答案是不会的。因为为了安全,我的服务器现在只打开了22这一个端口,而我TCP的端口号范围是[32768,60999]之间,两者没有交集。因此,服务器用几个端口就开放几个端口,是一种非常好的运维习惯。

参考

以上是关于手把手写C++服务器(12):TCP自连接原理Python示例解决方案的主要内容,如果未能解决你的问题,请参考以下文章

手把手写C++服务器(18):TCP紧急传输的方法——带外数据 (原理与代码示例)

手把手写C++服务器(24):socket响应一般框架TCP修改缓冲区内核监听listen最大长度

手把手写C++服务器(15):网络编程入门第一个TCP项目

手把手写C++服务器(14):基于UDP测量两台机器之间的网络延迟

手把手写C++服务器(30):手撕代码——基于TCP/IP的抛弃服务discard

手把手写C++服务器(17):自测!TCP协议面试经典十连问