TCP非阻塞及套接字异常处理:
TCP阻塞套接字异常捕获:
- 套接字创建失败,8000
- socket.error
- 客户端连接错误:
- ConnectionRefusedError
- socket.gaierror
- c.settimeout(1):
- 设置客户端超时
- 如果超时,引发:socket.timeout
- 如果不设置该属性,引发的异常是:TimeoutError
- 客户端套接字连接:
- TCP:连接成功
- 连接之后:不可以,无法重复
- 连接不成功的话,也无法继续使用,因为套接字中的数据包和连接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对1的专心服务
- TCP非阻塞
- s.setblocking(0) #0是费阻塞,1是阻塞
- 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