34.TCP非阻塞连接及套接字异常处理丶端口扫描脚本

TCP非阻塞及套接字异常处理:


 TCP阻塞套接字异常捕获:

  • 套接字创建失败,8000
  1.  socket.error
  •  客户端连接错误:
  1.  ConnectionRefusedError
  2. socket.gaierror
  •  c.settimeout(1):
  1. 设置客户端超时
  2. 如果超时,引发:socket.timeout 
  3. 如果不设置该属性,引发的异常是:TimeoutError
  •  客户端套接字连接:
  1.  TCP:连接成功
  2. 连接之后:不可以,无法重复
  3. 连接不成功的话,也无法继续使用,因为套接字中的数据包和连接IP端口已经构建好了

1,tcp_server.py

import socket
try:
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#ipv4,tsp协议
    ip = ''
    port = 22
    s.bind( (ip,port))   #只有服务端才会bind
    s.listen(5) #不是最大连接数,是最大连接等待数
except socket.error:
    print('[E] Create socket failed')
while True:
    try:
        c,c_addr = s.accept() #阻塞
        while True:
            date = c.recv(1024) #接受
            #date二进制
            if date:
                c.send(date.decode().upper().encode()) #发送全大写的
            else:
                c.close()   #关闭套接字
                break
    except KeyboardInterrupt:
        c.close()
        break
s.close()

2.tcp_client.py 

import socket
import sys
try:
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    ip = '192.168.137.128'
    port = 22
#    s.settimeout(2)  #设置客户端连接超时时间
    s.connect( (ip,port) )
except socket.error:
    print('[E] Create Socket Failed')
    s.close()
except socket.gaierror:
    print('[E] Failed To Connect Server')
    s.close()
except ConnectionRefusedError:
    print('[E] Server Refuse')
    s.close()
except socket.timeout:   #有效连接超时错误
    print('[E] Connect Timeout')
    s.close()
'''
except TimeoutError:
    print('[E] 连接超时')
'''
else:
    while True:
        try:
            msg = input('>>> ')
            s.send(msg.encode('utf-8'))
            date = s.recv(1024)
            if date:
                print('[服务器]:',date.decode('utf-8'))
            else:
                s.close()
                break
        except KeyboardInterrupt:
            s.close()
            break

TCP端口扫描.py

#ssh TCP 22
import socket
import sys
ip = input('IP:>>> ')
open_port = []  #存储扫描成功链接的端口
try:
    for port in range(1,65535):   #一般端口的取值范围
        try:
            s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            s.settimeout(0.5)  #设置客户端连接超时时间 超过0.5s 则失败
        except socket.error:
            sys.exit('套接字创建失败')
        else:
            try:
                s.connect ( (ip,port) )
            except socket.timeout:  # 如果出现端口不通,那么代表端口关闭
                print('[closed]:%s' % port)
            else:
                s.close()
                open_port.append(port)
            del s  #套接字连接成功或者不成功,都无法继续使用,因为套接字中的数据包和连接IP端口已经构建好了,必须删除套接字才能继续循环下一个端口
    else:
        print('Open:%s' % open_port)
except KeyboardInterrupt:
    print('终止...')
    sys.exit()

运行结果: 

IP:>>> 192.168.137.130
[closed]:1
[closed]:2
[closed]:3
[closed]:4
[closed]:5
终止... 

TCP非阻塞:(企业用的最多,tcp服务器同时允许多个客户端连接)

  • 默认是阻塞的:
  1. 有人来吗?没人来连接会死等
  2. 专心致志服务你,其他人管不了了,1对1的专心服务
  • TCP非阻塞
  1. s.setblocking(0)    #0是费阻塞,1是阻塞
  2. BlockingIOError: [WinError 10035] 无法立即完成一个非阻止性套接字操作。这是一个不可避免的报错 ,所有我们要自定义异常报错
  • fzs_tcp_server.py
    import socket
    import copy
    try:
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#ipv4,tsp协议
        s.bind( ('',8022))   #只有服务端才会bind
        s.listen(5) #不是最大连接数,是最大连接等待数
        s.setblocking(0) #1是阻塞 0是非阻塞
        connect_client = {} #创建一个dict
        connect_client_bak = {}
    except socket.error:
        print('[E] Create socket failed')
    while True:
        try:
            try:
                c,c_addr = s.accept() #阻塞
                #非阻塞,没有人来,我也会向下运行
            except BlockingIOError:         #没有人来连接 会报错
                #print('暂时没有人来连接...')
                pass
            else:
                c.setblocking(0)
                connect_client[c] = c_addr # 这个dict就是我的所有连接客户
                #key:是套接字
                #value: 地址 
                connect_client_bak = copy.copy(connect_client) #拷贝
            for client in connect_client_bak:
                if not client in connect_client: #客户端是真正连接的有效存在的
                    continue 
                try:
                    date = client.recv(1024)
                except BlockingIOError:
                    #print('[%s:%s]:没说话...' %  connect_client[client]) #打印出这个没说话的地址,connect_client[client]根据字典取出的值返回的是元组数据,列如:('192.168.137.130',8080)
                    pass
                else:
                    if date:
                        print('[%s]:%s' % (connect_client[client],date.decode('utf-8')) )
                        while True:
                            msg = input('>>> ')
                            if msg:
                                client.send(msg.encode('utf-8'))
                                break
                            else:
                                print('回复消息不能为空,请重新回复')
                    else:
                        print('[%s:%s]这人走了' % connect_client[client])
                        del connect_client[client]
                    del date
        except KeyboardInterrupt:
            break
    s.close()
    
  • fzs_tcp_client.py

    import socket
    import sys
    try:
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        ip = '192.168.137.128'
        port = 8022
    #    s.settimeout(2)  #设置客户端连接超时时间
        s.connect( (ip,port) )
    except socket.error:
        print('[E] Create Socket Failed')
        s.close()
    except socket.gaierror:
        print('[E] Failed To Connect Server')
        s.close()
    except ConnectionRefusedError:
        print('[E] Server Refuse')
        s.close()
    except socket.timeout:   #有效连接超时错误
        print('[E] Connect Timeout')
        s.close()
    except socket.timeout:
        print('[E] Timeout')
        s.close()
    else:
        while True:
            try:
                msg = input('>>> ')
                s.send(msg.encode('utf-8'))
                date = s.recv(1024)
                if date:
                    print('[服务器]:',date.decode('utf-8'))
                else:
                    s.close()
                    break
            except KeyboardInterrupt:
                s.close()
                break
    
  • 运行结果

    ^C[root@localhost date]# python3 fzs_tcp_server.py 
    [('192.168.137.1', 49856)]:111
    >>> 1111
    [('192.168.137.130', 49291)]:222
    >>> 2222
    [('192.168.137.130', 49291)]:aaa
    >>> aaaa
    [('192.168.137.1', 49856)]:bbb
    >>> bbbb
    [('192.168.137.1', 49856)]:zzzzzzzzzzzzzzz
    >>> zzz
    [('192.168.137.130', 49291)]:ccccccccccccccccccccccc
    >>> ccc
    

      

原文地址:https://www.cnblogs.com/zhangan/p/10157196.html