2023年7月15日发(作者:)
SOCKET编程本节内容:1. Socket语法及相关2. SocketServer实现多并发 SOCKET语法及相关socket概念socket本质上就是在2台⽹络互通的电脑之间,架设⼀个通道,两台电脑通过这个通道来实现数据的互相传递。 我们知道⽹络 通信 都 是基于 ip+port ⽅能定位到⽬标的具体机器上的具体服务,操作系统有0-65535个端⼝,每个端⼝都可以独⽴对外提供服务,如果 把⼀个公司⽐做⼀台电脑 ,那公司的总机号码就相当于ip地址, 每个员⼯的分机号就相当于端⼝, 你想找公司某个⼈,必须 先打电话到总机,然后再转分机 。建⽴⼀个socket必须⾄少有2端, ⼀个服务端,⼀个客户端, 服务端被动等待并接收请求,客户端主动发起请求, 连接建⽴之后,双⽅可以互发数据。
Socket Families(地址簇)_UNIX unix本机进程间通信
_INET IPV4 _INET6 IPV6
Socket _STREAM #for _DGRAM #for udp
_RAW #原始套接字,普通的套接字⽆法处理ICMP、IGMP等⽹络报⽂,⽽SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报⽂;此外,利⽤原始套接字,可以通过IP_HDRINCL套接字选项由⽤户构造IP头。_RDM #是⼀种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM⽤来提供对原始协议的低级访问,在需要执⾏某些特殊操作时使⽤,如发送ICMP报⽂。SOCK_RAM通常仅限于⾼级⽤户或管理员运⾏的程序使⽤。_SEQPACKET #废弃了
Socket ⽅法(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)rinfo(host, port, family=0, type=0, proto=0, flags=0) #获取要连接的对端主机地址(address) (address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表⽰地址。(backlog) 开始监听传⼊连接。backlog指定在拒绝连接之前,可以挂起的最⼤连接数量。 backlog等于5,表⽰内核已经接到了连接请求,但服务器还没有调⽤accept进⾏处理的连接个数最⼤为5 这个值不能⽆限⼤,因为要在内核中维护连接队列cking(bool) 是否阻塞(默认True),如果设置False,那么accept和recv时⼀旦⽆数据,则报错。() 接受连接并返回(conn,address),其中conn是新的套接字对象,可以⽤来接收和发送数据。address是连接客户端的地址。 接收TCP 客户的连接(阻塞式)等待连接的到来t(address) 连接到address处的套接字。⼀般,address的格式为元组(hostname,port),如果连接出错,返回错误。t_ex(address) 同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:() 关闭套接字(bufsize[,flag]) 接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。om(bufsize[.flag]) 与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。(string[,flag]) 将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能⼩于string的字节⼤⼩。即:可能未将指定内容全部发送。l(string[,flag]) 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 内部通过递归调⽤send,将所有内容发送出去。(string[,flag],address) 将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要⽤于UDP协议。eout(timeout) 设置套接字操作的超时期,timeout是⼀个浮点数,单位是秒。值为None表⽰没有超时期。⼀般,超时期应该在刚创建套接字时设置,因为它们可能⽤于连接的操作(如 client 连接最多等待5s )rname() 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。kname() 返回套接字⾃⼰的地址。通常是⼀个元组(ipaddr,port)() 套接字的⽂件描述符le(file, offset=0, count=None) 发送⽂件 ,但⽬前多数情况下并⽆什么卵⽤。
简单发送消息socket server端import socket# 定义协议类型,默认可以对照上⾯参考server = () # 声明SOCKET类型,同时⽣成SOCKET连接对象(('localhost',6999)) # 绑定监听端⼝() # 监听,最⼤多少个连接,挂起的连接print('kaishi deng dianhua')while True: conn, addr = () # 等电话打进来 print('dianhua lai le') print(conn, addr) # CONN就是客户端连过来⽽在服务器端为其⽣成的⼀个连接实例 while True: data = (1024) # 接收消息 print('recv:', data) if not data: print('close conn') break (()) # 发送 # l() # 发送全部,不⼀定会好使() 客户端# !/usr/bin/env python# _*_coding:utf-8_*_# Author:Jokerimport socket# 定义协议类型,默认可以对照上⾯参考client = () # 声明SOCKET类型,同时⽣成SOCKET连接对象t(('localhost',6999))while True: msg = input('>>>:').strip() if len(msg) == 0:continue (('utf-8')) data = (1024) # 1024 字节 print('recv',())()
利⽤socket模拟ssh远程执⾏命令socket server端# !/usr/bin/env python# _*_coding:utf-8_*_# Author:Jokerimport socketimport os,timeserver = ()(('localhost', 9996))()while True: conn, addr = () print('new conn:', addr) while True: data = (1024) if not data: print('客户端已断开') break print('执⾏指令:', data) cmd_res = (()).read() if len(cmd_res) == 0: cmd_res = 'cmd has no output' (str(len(cmd_())).encode('utf-8')) # 发送⼤⼩给客户端 # (1) # 通过缓冲区超时,来解决粘包问题 client_ack = (1024) # wait client to confirm # 等待确认 print('ack from client:',client_ack) (cmd_('utf-8'))() client# !/usr/bin/env python# _*_coding:utf-8_*_# Author:Jokerimport socketclient = ()t(('localhost',9996))while True: cmd = input('>>>:').strip() if len(cmd) == 0:continue (('utf-8')) cmd_res_size = (1024) # 接收命令结果的长度 print('命令结果⼤⼩',cmd_res_size) ('我准备好了'.encode()) received_size = 0 received_data = b'' while received_size < int(cmd_res_()): data = (1024) received_size += len(data) # 每次收到的有可能⼩于1024,所以必须⽤LEN判断 received_data += data else: print('receve done',received_size) print(received_())()# 因为缓冲区的问题,很可能会执⾏的命令的结果缓冲在这个BUFFERS⾥⾯,所以客户端再收的时候会从这个BUFFERS⾥⾯取 利⽤socket模拟ftpsocket server端# !/usr/bin/env python# _*_coding:utf-8_*_# Author:Jokerimport socket,hashlibimport osserver = ()(('localhost', 9996))()while True: conn,addr = () while True: print('等待指令') data = (1024) if not data: print('客户端已断开') break cmd, filename = ().split() # GET FILENAME print(filename) if (filename): f = open(filename, 'rb') m = 5() file_size = (filename).st_size (str(file_size).encode()) # SEND FILENAME (1024) # 客户端确认准备好 for line in f: (line) (line) # 发送 print('file md5',est()) () (est().encode()) # 最后发送MD5值 print('send done')()client# !/usr/bin/env python# _*_coding:utf-8_*_# Author:Jokerimport socket,hashlibclient = ()t(('localhost',9996))while True: cmd = input('>>>:').strip() if len(cmd) == 0:continue if with('get'): (()) server_response = (1024) print('server response:',server_response) (b'ready to recv file') file_total_size = int(server_()) received_size = 0 filename = ()[1] f = open(filename + '.new','wb') m = 5 while received_size < file_total_size: if file_total_size - received_size > 1024: # 要收的不⽌⼀次 size = 1024 else: # 最后⼀次,剩多少收多少 size = file_total_size - received_size print('last receive',size) data = (size) received_size += len(data) (data) (data) else: new_file_md5 = est() print('file recv done',received_size,file_total_size) () server_file_md5 = (1024) print('server file md5:',server_file_md5) print('client file md5:',new_file_md5)()# 因为缓冲区的问题,很可能会执⾏的命令的结果缓冲在这个BUFFERS⾥⾯,所以客户端再收的时候会从这个BUFFERS⾥⾯取
SocketServer# ⼀共⼏种类型class ver(server_address, RequestHandlerClass, bind_and_activate=True)class ver(server_address, RequestHandlerClass, bind_and_activate=True)class reamServer(server_address, RequestHandlerClass, bind_and_activate=True) unix tcpclass tagramServer(server_address, RequestHandlerClass, bind_and_activate=True) unix udp+------------+| BaseServer |+------------+|v+-----------+ +------------------+| TCPServer | -------> | UnixStreamServer |+-----------+ +------------------+|v+-----------+ +--------------------+| UDPServer | -------> | UnixDatagramServer |+-----------+ +--------------------+创建 SOCKETSERVE步骤1。创建请求处理类,并且这个类要继承BASEREQUESTHANDLE,并且还要重写⽗类的HANDLE()2。实例化SERVER CLASSE,TCPSERVE,并且传递SERVER IP 和你上⾯创建的请求处理类给这个TCPSERVER3。_REQUEST() 处理⼀个请求_FOREVER() 处理多个请求,永远执⾏4。lass
gTCPServerclass
gUDPServerclass
ingTCPServerclass
ingUDPServer
sockerserver server端import socketserverclass MyTCPHandler(questHandler): def handle(self): while True: try: = (1024).strip() print('{}wrote:'.format(_address[0])) print() except ConnectionResetError as e: print('err',e) breakif __name__ == '__main__': HOST,PORT = 'localhost',9999 server = ver((HOST,PORT),MyTCPHandler) _forever()server = ingTCPServer # 线程server = gTCPServer # 进程 clientimport socket# 定义协议类型,默认可以对照上⾯参考client = () # 声明SOCKET类型,同时⽣成SOCKET连接对象t(('localhost',6999))while True: msg = input('>>>:').strip() if len(msg) == 0:continue (('utf-8')) data = (1024) # 1024 字节 print('recv',())()
作业1:⽤socketserver继续完善FTP作业作业2:开发⼀个批量主机管理⼯具需求:1. 可以对机器进⾏分组2. 可以对指定的⼀组或多组机器执⾏批量命令,分发⽂件(发送接收)3. 纪录操作⽇志
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1689410047a243515.html
评论列表(0条)