python——网络编程
socket
简单讲先是server端发布一个服务,提供端口和IP,监听起来,就OK了。通过socket.send(bytes)给客户端发送消息,通过socket.recv(bytes)接收客户端的数据,进行处理
#!/user/bin/env python # -*- coding:utf-8 -*- # 模拟ssh import socket, subprocess #获取socket对象 s = socket.socket() #获取socket参数 ip_port = (socket.gethostname(), 1234) ip_port = (socket.gethostname(), 1234) #创建服务 s.bind(ip_port) #开启监听 s.listen(5) while True: #等待连接 conn, addr = s.accept() print(conn.getsockname(),"连接服务") while True: #获取连接消息 res = conn.recv(1024) send_data = res p = subprocess.Popen(str(res, encoding='utf-8'), shell = True, stdout = subprocess.PIPE) send_data = p.stdout.read() print(type(send_data)) if len(res) == 0: print(conn.getsockname(),'断开服务') break if send_data: send_data = str(send_data,encoding='gbk') else: send_data = 'command error!' print(send_data) #发送消息 len_data = len(bytes(send_data,encoding='utf-8')) conn.send(bytes("%d"%len_data, encoding='utf-8')) to_recv = str(conn.recv(1024),encoding = 'utf-8') print(to_recv) if to_recv == 'Y' or to_recv == 'y': conn.send(bytes(send_data,encoding='utf-8')) else: print('不接收') conn.send(bytes("OK!不接收!",encoding='utf-8')) #关闭连接 conn.close()
然后客户端根据提供的端口和IP去连接,通过socket.spend(bytes)发送数据给服务端,通过socket.recv(bytes)接收服务端数据
#!/user/bin/env python # -*- coding:utf-8 -*- # Author:hft import socket c = socket.socket() ip_port = ("192.168.50.128", 1234) c.connect(ip_port) #发送消息 while True: sent_data = input(">>:") if sent_data == 'q' or sent_data == 'Q': break c.send(bytes(sent_data, encoding='utf-8')) res = int(str(c.recv(1024), encoding='utf-8')) print("字节长度为:",res,"是否收(Y/N)") to_recv = input(">>") c.send(bytes(to_recv, encoding='utf-8')) # recv_size = 0 # recv_msg = b'' # while recv_size < res: # recv_data = c.recv(1024) # recv_msg += recv_data # recv_size += len(recv_data) # print(recv_size,res) recv_msg = c.recv(res) print(str(recv_msg, encoding='utf-8')) c.close()
socket listen 提供可以有多少个连接
socket 粘包 如果接收数据长度超过recv的数值,则会被下一个recv函数去接收上个未接受完的数据,所以如果数据过长,需对数据长度进行判断,如果没有接收完,需写个循环持续接收,万不能一次接收很大的数据,这样会对网络有压力
socket 阻断 recv 和 append都有阻断效果,即没有数据或者链接过来,程序处于假死状态,一旦触发才会进行下面的代码
socketserver
socket在单对单链接时是没有问题的,但是网络的概念就是一对多或多对多的概念,而socket如果当下的链接未断开,则其他链接都会处于挂起状态,直到当前链接断开。socketserver提供了一个多线程的链接方式,通过它可以实现多并发的需求
多并发 多并发即是可以多个客户端链接一个服务端,而彼此不会有影响。
例子 ssh
#!/user/bin/env python # -*- coding:utf-8 -*- # ssh import socketserver, subprocess class MyServer(socketserver.BaseRequestHandler): def handle(self): conn = self.request print(conn.getsockname(), "连接服务") while True: # 获取连接消息 try: res = conn.recv(1024) send_data = res p = subprocess.Popen(str(res, encoding='utf-8'), shell=True, stdout=subprocess.PIPE) send_data = p.stdout.read() print(type(send_data)) if len(res) == 0: print(conn.getsockname(), '断开服务') break if send_data: send_data = str(send_data, encoding='gbk') else: send_data = 'command error!' print(send_data) # 发送消息 len_data = len(bytes(send_data, encoding='utf-8')) conn.sendall(bytes("%d" % len_data, encoding='utf-8')) to_recv = str(conn.recv(1024), encoding='utf-8') print(to_recv) if to_recv == 'Y' or to_recv == 'y': conn.sendall(bytes(send_data, encoding='utf-8')) else: print('不接收') conn.sendall(bytes("OK!不接收!", encoding='utf-8')) except Exception: print("异常!") break if __name__ == '__main__': server = socketserver.ThreadingTCPServer(('192.168.11.86',1234), MyServer) server.serve_forever()
多线程
python中通过threading来实现多线程,通过调用threading.Thread来调用不同的线程
threading.Thread(target=f1,args=(123,)):
target:是调用的函数
args:是函数的参数,是元组类型
setDaemon:默认值为False:表示主线程等待子线程结束 才会结束
True:表示主线程不等待子线程结束,如果主线程先结束,则程序会直接结束
start:表示线程开始执行,前面无论定义了多少东西,都到这步才会开始执行线程。
import time ,threading, datetime # def f1(i): # time.sleep(1) # print(i) # print(datetime.datetime.now()) # # print(datetime.datetime.now()) # for j in range(10): # t1 = threading.Thread(target=f1, args=(j,)) # t1.start() def f1(arg): time.sleep(0.5) print(datetime.datetime.now()) print(arg) print(datetime.datetime.now()) t = threading.Thread(target=f1, args=(123,)) # f1(111) t.setDaemon(True)#True,表示主线程不等待此子线程执行完毕。 t.start()#开始执行 t.join(0.9)#表示主线程到此,等待,直到子线程执行完毕, #参数,表示主线程在此处至多等待N秒,然后执行下面代码 print('end')
作用域
旧事重提,作用域,python作用域有几种情况
首先块级作用域,python中没有块级作用域,即一个方法、一个代码块中,无论在哪里定义了变量,在它的下面的代码块中都可调用、修改等:
a = 0 while a<1: a += 1 b = 1 print(a,b) 执行结果:1 1
然后方法之间的变量是不可以直接调用,需要传参才可以进行变量的调用,需要返回值,才能进行变量修改:
def f1(): a = 1 def f2(): b = a f2() 报错: NameError: name 'a' is not defined
全局变量,这类变量可以在模块任何一处使用,不可直接去赋值,需要添加golable
a = 1 c = 1 b = [] def f1(): a = 2 b.append(2) global c c = 2 print(a,b,c) def f2(): print(a,b,c) f1() f2()
执行结果:
2 [2] 2 1 [2] 2