socketserve及其应用

1.cmd命令 利用socket

socket服务端

 1 import socket
 2 import subprocess
 3 s = socket.socket()
 4 s.bind(("127.0.0.1",8000))
 5 s.listen(3)
 6 print("waiting...")
 7 while 1:
 8     conn,addr = s.accept()
 9     print(conn)
10     while 1:
11         try:
12             a = conn.recv(1024)
13         except Exception:
14             break
15         if not a:
16             break
17         print(">>>",str(a,"utf8"))
18         obj  = subprocess.Popen(a.decode("utf8"),shell=True,stdout=subprocess.PIPE)
19         result = obj.stdout.read()
20         print('ooooo',type(result))
21         result_len = bytes(str(len(result)),"utf8") # result是unicode编码下的十六进制 所以先转换成字符串(Unicode) 在转换成bytes
22         conn.sendall(result_len)  # 两个send在一起容易发生粘包 特别是第一个数据特别小的时候
23         conn.sendall(result)      # 所以在send之间在来个一收一发
24 s.close()

client客户端

 1 import socket
 2 s = socket.socket()
 3 ss = ("127.0.0.1",8000)
 4 s.connect(ss)
 5 while 1:
 6     inp = input(">>>")
 7     if inp =="q":
 8         break
 9     s.send(bytes(inp,"utf8"))    # send 传送智能是bytes类型
10     result_len = int(str(s.recv(1024),"utf8"))    # 二进制的不能直接转换成整形!!!
11     print(result_len)
12     data = bytes()
13     while len(data)!=result_len:    # 大文件传输过程中  不能一次传完 造成延迟 所以要先
14         data += s.recv(1024)    # 传输文件的大小 根据大小判断文件传输
15     print(str(data,"gbk"))
16 s.close()

上述的代码实现了client端发送cmd指令到serve端进行执行后返回给client端结果的一个过程。

attention:一发一收

socket创建

  s = socket.socket()这样就创建了一个socket对象。在serve端和client端分别需要创建一个。括号中仍有4个默认函数:

  family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None

  其中family是IPV4 的默认值,type是TCP的默认值。

设置值

  创建好socket之后,serve端需要设置(4,5行)

  1 bind绑定IP和端口。

  2 listening值是最多等待。

  3 接受client协议和地址 即 第八行

  4 注意这里的conn就是client端的.socket 所以在接收的时候为conn.receive

  client端只用设置连接的address和端口。

小细节

  1.serve端的try是防止client端直接结束造成接收报错。

  2.若接收的a为空表示client端主动断开了socket连接(本身发送不能发送空)。

关于subprocess

  obj = subprocess.Popen(a.decode("utf8"),shell=True,stdout=subprocess.PIPE)
  result = obj.stdout.read()

  这两句话实现了cmd在子程序中运行后返回结果到result。

  注意这里的result是gbk编码下的bytes类型。

关于这其中杂乱的编码

  Python3中有两种格式:

    str:str>>bytes 称为编码(encode)方法有1.re=bytes(“ccc”,“utf8”)2.re=“ccc”.encode(“utf8”)py3中str都是Unicode编码。兼容utf8,三字节表示中文。

    bytes:bytes>>str称为解码(decode)方法有1.re = str(“ccc”,“utf8”)2.re=“ccc”.decode(“utf8”)bytes类型有相对应的编码协议。即什么样的编码形式               (如utf8)就仍用什么样的解码。

  Python2中也有两种:

    str:即原来的3中的bytes

    Unicode:即str u“你好” 表示内容用的Unicode编码。

  pyhton3中页面用到utf8,2中用的阿斯克码。

大文件传输问题解决

  发送端的sendall必将数据都发送过去,但是接收的时候一次最多接收设置值1024个字节。(received值最大8K)所以造成接收时显示缓慢。(接收第二条时仍旧显示第      一条)

  解决办法是:多次循环接收直到data大小等于文件大小。while len(data)!=result_len:不相等就继续接收。

 2.socketserve

serve端

 1 import socketserver
 2 class Myserve(socketserver.BaseRequestHandler):
 3     def handle(self):
 4         print("active")
 5         while 1:
 6             conn = self.request
 7             print(self.client_address)
 8             while 1:
 9                 a = conn.recv(1024)
10                 print(">>>", str(a, "utf8"))
11                 if not a:
12                     break
13                 inp = input(">>>")
14                 conn.send(bytes(inp, "utf8"))
15             conn.close()
16 mine = socketserver.ThreadingTCPServer(("127.0.0.1",8000),Myserve)
17 mine.serve_forever()

上述通过调用socketserver实现了多个client和一个server进行通信的功能。

实现过程:

  创建一个自己命名的server类myserver

  只在此类中创建一个方法:handle名字不能变,逻辑按照功能设计

  创建socketserver对象,调用ThreadingTCPServer方法传入address元组,和server。

  serverforever()激活这个并发的server。

  

原文地址:https://www.cnblogs.com/khal-Cgg/p/5919236.html