socket基本语法

#!/usr/bin/env python # -*- coding: utf-8 -*- ''' python3 socket收发消息都是只能使用bytes类型,而python2.7则可以使用str类型 ''' import socket #创建socket对象 s = socket.socket() #创建socket对象 s.settimeout(5) #设置超时时间 s.getpeername() #客户端使用,返回服务端的套接字地址(ip、端口号) #连接服务端 ip_port = ('127.0.0.1',9999) #定义ip、端口号 s.connect(ip_port) #socket对象连接服务端。(ip、端口号一定是元组形式) ----连接失败会报错 #s.connect_ex(ip_port) #功能同上,不过如果连接失败会返回一个错误编码(不报错) #发消息 send_data = '你好' s.send(bytes(send_data,encoding='utf-8')) #发送消息,成功返回发送的字节数-----python3只能发送字节类型(bytes),python2.7可以直接发送字符串 #s.sendall(bytes(send_data,encoding='utf-8')) #发送所有数据,成功返回None,失败报错 #收消息 recv_data = s.recv(1024) #关闭 s.close()

#!/usr/bin/env python # -*- coding: utf-8 -*- ''' python3 socket收发消息都是只能使用bytes类型,而python2.7则可以使用str类型 ''' ''' sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) 参数一:地址簇 socket.AF_INET IPv4(默认) socket.AF_INET6 IPv6 socket.AF_UNIX 只能够用于单一的Unix系统进程间通信 参数二:类型 socket.SOCK_STREAM 流式socket , for TCP (默认) socket.SOCK_DGRAM 数据报式socket , for UDP socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理 特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。 socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要 执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。 socket.SOCK_SEQPACKET 可靠的连续数据包服务 参数三:协议 0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议 ''' import socket #创建socket对象 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) #创建socket对象 #绑定 ip_port = ('127.0.0.1',9999) #定义ip、端口号 s.bind(ip_port) #socket对象绑定ip、端口号(ip、端口号一定是元组形式) s.getsockname() #服务端使用,返回服务端自身的套接字地址(ip、端口号) #监听,并设置最大挂起连接数 s.listen(5) #监听,除了正在连接的客户端,最多还能能挂起5个连接,超过之后就拒绝连接 #获取客户端连接 conn, addr = s.accept() #获取客户端的scoket对象conn和客户端的地址address(ip、端口号) #收发消息 recv_data = conn.recv(1024) #socket获取的客户端对象(conn)用来接收消息 print(str(recv_data,encoding='utf-8')) send_data = '你好' conn.send(bytes(send_data,encoding='utf-8')) #socket获取的客户端对象(conn)用来发送消息-----python3只能发送字节类型(bytes),python2.7可以直接发送字符串 #关闭客户端对象 conn.close()
socket交互
简单交互

#!/usr/bin/env python # -*- coding: utf-8 -*- import socket #客户端创建socket对象 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) ip_port = ('127.0.0.1',9999) #使用connect方法连接服务端,连接失败会报错 #也可以使用connect_ex方法,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回失败编码,例如:10061 client.connect(ip_port) while True: # 从服务端获取数据 recv_data = client.recv(1024) print('Server:',str(recv_data,encoding='utf-8')) # 客户端发送数据 s = input('Client:').strip() if len(s) == 0: break client.send(bytes(s,encoding='utf-8')) if s == 'exit': break

#!/usr/bin/env python # -*- coding: utf-8 -*- import socket #创建一个socket对象 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) ip_port = ('127.0.0.1',9999) #绑定ip和端口号 sock.bind(ip_port) #设置最大连接数 sock.listen(5) while True: #使用accept方法获取一个客户端连接 #获取客户端的scoket对象conn和客户端的地址(ip、端口号)address conn,address = sock.accept() # 给客户端发信息 send_data = 'Hello.' conn.send(bytes(send_data,encoding='utf-8')) while True: try: # 接收客户端消息 recv_data = conn.recv(1024) print('Client:',str(recv_data,encoding='utf-8')) #检测客户端发出退出指令,关闭连接 if str(recv_data,encoding='utf-8') == 'exit': break s = input('Server:').strip() if len(s) == 0: break conn.send(bytes(s,encoding='utf-8')) except Exception as e: break # 关闭客户端的socket连接 conn.close()
简单ssh交互

#!/usr/bin/env python # -*- coding: utf-8 -*- import socket #客户端创建socket对象 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) ip_port = ('127.0.0.1',9999) #使用connect方法连接服务端,连接失败会报错 #也可以使用connect_ex方法,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回失败编码,例如:10061 client.connect(ip_port) while True: # 客户端发送数据 s = input('Client:').strip() if len(s) == 0: break client.send(bytes(s,encoding='utf-8')) if s == 'exit': break # 从服务端获取数据 recv_data = client.recv(4096) print('Server:',str(recv_data,encoding='utf-8')) # print(str(recv_data))

#!/usr/bin/env python # -*- coding: utf-8 -*- import socket import subprocess #创建一个socket对象 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) ip_port = ('127.0.0.1',9999) #绑定ip和端口号 sock.bind(ip_port) #设置最大连接数 sock.listen(5) while True: #使用accept方法获取一个客户端连接 #获取客户端的scoket对象conn和客户端的地址(ip、端口号)address conn,address = sock.accept() while True: try: # 接收客户端消息 recv_data = conn.recv(1024) #检测客户端发出退出指令,关闭连接 if str(recv_data,encoding='utf-8') == 'exit': break p = subprocess.Popen(str(recv_data,encoding='utf-8'),shell=True,stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE) #执行命令 res = p.stdout.read() #只能读取一次(读,并取出),第二次读取就为空 if len(res) == 0: #判断输出结果的长度,如果为0,表示命令执行错误 res = p.stderr.read() #读取错误信息 send_data = str(res,encoding='gbk') #将结果解码 # print(send_data) conn.send(bytes(send_data,encoding='utf-8')) #将结果发送到客户端 except Exception as e: break # 关闭客户端的socket连接 conn.close()
粘包问题

#!/usr/bin/env python # -*- coding: utf-8 -*- ''' 粘包:客户端每次接收数据都有大小限制(如:1024),当接收的数据小于服务端发送的数据时(数据没有接收完),多余的数据就会堆积, 当客户端下次再从服务端获取数据时,先获得的则是上次服务端没有传完的数据。这就是粘包现象 那么怎么才能使每次服务端向客户端发送的数据完全接收呢? 解决:服务端告诉客户端要发送的数据长度,客户端循环来收取服务端发送的数据,直到接收的数据长度等于服务端告诉的长度,就停止接收 ''' import socket #客户端创建socket对象 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) ip_port = ('127.0.0.1',9999) #使用connect方法连接服务端,连接失败会报错 #也可以使用connect_ex方法,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回失败编码,例如:10061 client.connect(ip_port) while True: # 客户端发送数据 s = input('Client:').strip() if len(s) == 0: break client.send(bytes(s,encoding='utf-8')) if s == 'exit': break ready_data = str(client.recv((1024)),encoding='utf-8') #获取服务端发送过来的数据长度信息 if ready_data.startswith('Ready'): msg_size = int(ready_data.split('|')[1]) #获取信息长度 client.send(bytes('Start',encoding='utf-8')) #告诉服务端可以正式发送数据了 recv_size = 0 #已经获取的数据长度 recv_msg = b'' #存放服务端发来的数据(以字节格式进行存放) #循环收取服务端发来的数据(每次只接收1024字节) while recv_size < msg_size: #当已经获取的数据长度小于数据总长时,表示数据还没有接收完成,继续接收,直到接收的数据长度大于等于数据总长,就停止接收 recv_data = client.recv(1024) recv_msg += recv_data #将每次获取的数据拼接到接收的数据字符串上 recv_size += len(recv_data) #统计已获取数据的长度 print('数据总长:%s,已接收数据长度:%s'%(msg_size,recv_size)) print('Server:',str(recv_msg,encoding='utf-8'))

#!/usr/bin/env python # -*- coding: utf-8 -*- ''' 粘包:客户端每次接收数据都有大小限制(如:1024),当接收的数据小于服务端发送的数据时(数据没有接收完),多余的数据就会堆积, 当客户端下次再从服务端获取数据时,先获得的则是上次服务端没有传完的数据。这就是粘包现象 那么怎么才能使每次服务端向客户端发送的数据完全接收呢? 解决:服务端告诉客户端要发送的数据长度,客户端循环来收取服务端发送的数据,直到接收的数据长度等于服务端告诉的长度,就停止接收 ''' import socket import subprocess #创建一个socket对象 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) ip_port = ('127.0.0.1',9999) #绑定ip和端口号 sock.bind(ip_port) #设置最大连接数 sock.listen(5) while True: #使用accept方法获取一个客户端连接 #获取客户端的scoket对象conn和客户端的地址(ip、端口号)address conn,address = sock.accept() while True: try: # 接收客户端消息 recv_data = conn.recv(1024) #检测客户端发出退出指令,关闭连接 if str(recv_data,encoding='utf-8') == 'exit': break p = subprocess.Popen(str(recv_data,encoding='utf-8'),shell=True,stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE) #执行命令 res = p.stdout.read() #只能读取一次(读,并取出),第二次读取就为空 if len(res) == 0: #判断输出结果的长度,如果为0,表示命令执行错误 res = p.stderr.read() #读取错误信息 send_data = bytes(str(res,encoding='gbk'),encoding='utf-8') #将结果解码,并转换成bytes格式 #print(str(send_data,encoding='utf-8')) conn.send(bytes('Ready|%s'%len(send_data),encoding='utf-8')) #向客户端发送send_data的长度,为下次正式发送数据做准备 send_flag = str(conn.recv(1024),encoding='utf-8') #获取客户端是否发送数据的标志位 #print(send_flag) if send_flag == 'Start': #标志位为Start,开始发送数据 conn.send(send_data) #将结果发送到客户端 except Exception as e: break # 关闭客户端的socket连接 conn.close()