Python网络编程
网络编程通信流程
sk.bind(address) # s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。 sk.listen(backlog) # 开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。 sk.setblocking(bool) # 是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。 sk.accept() # 接受连接并返回(conn,address),其中conn是建立连接的套接字对象,可用于数据操作。address是连接客户端的地址。 sk.connect(address) # 连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 sk.connect_ex(address) # 同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码。 sk.close() # 关闭套接字 sk.recv(bufsize[,flag]) # 接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。 sk.recvfrom(bufsize[.flag]) # 返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。 sk.send(string[,flag]) # 将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。 sk.sendall(string[,flag]) # 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。内部通过循环调用send,将所有内容发送出去。 sk.sendto(string[,flag],address) # 将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。 sk.settimeout(timeout) # 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。 sk.getpeername() # 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。 sk.getsockname() # 返回套接字自己的地址。通常是一个元组(ipaddr,port) sk.fileno() # 套接字的文件描述符
import socket, os # 创建一个INET,TCP套接字 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 监听的地址和端口 sk.bind(('127.0.0.1', 8080)) # 开始监听,可以指定等待的最大连接数,超过则拒绝连接 sk.listen(5) # 接受连接并返回(conn, address),conn为建立连接的套接字对象,address是客户端的地址端口 conn, address = sk.accept() # 接受对端发送的数据,bytes类型,最大1024 header_data = conn.recv(1024) header_data = str(header_data, 'utf8').split() mode, file_path, file_size = header_data file_size = int(file_size) file_name = os.path.basename(file_path) local_path = os.path.abspath(__file__) local_path = os.path.dirname(local_path) file_path = '\\'.join([local_path, file_name]) if mode == 'post': data_len = 0 with open(file_path, 'wb') as f: while data_len < file_size: recv_data = conn.recv(1024) f.write(recv_data) data_len += len(recv_data)
import socket, os # 创建INET,TCP套接字 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 发起套接字连接 sk.connect(('127.0.0.1', 8080)) request = input('>>>').split(' ') command, file = request file_path = os.path.abspath(file) file_size = os.stat(file_path).st_size file_size_str =str(file_size) request = ' '.join([command, file_path, file_size_str]) header_data = bytes(request, encoding='utf8') # 向建立连接的套接字,尝试发送所有数据,成功返回None,失败则抛出异常。 sk.sendall(header_data) data_len = 0 while data_len < file_size: with open(file_path, 'rb') as f: send_data = f.read(1024) sk.sendall(send_data) data_len += len(send_data) sk.close() print('%s successed' % command)
socketserver模块
I/O多路复用指:通过一种机制,可以监视多个描述符(socket),一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。
import socketserver # 创建一个BaseRequestHandler继承类,重写handle方法 class MyServer(socketserver.BaseRequestHandler): def handle(self): print('start') while True: data = self.request.recv(1024) print(data, 'sd') if not data: break self.request.send(data) data = str(data, 'utf8') print(data) # 实例化一个多线程的socket套接字对象 sk = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer) # 调用serve_forever方法,执行重写后的handle方法 sk.serve_forever()
import socket sk = socket.socket() sk .connect(('127.0.0.1', 8080)) while True: data = input('>>>') if not data: break data = bytes(data, 'utf8') sk.sendall(data) recv_data = sk.recv(1024) recv_data = str(recv_data, 'utf8') print(recv_data) sk.close()