python学习笔记(socket模块)

1、socket模块使用要分为服务端及客户端,服务端用于接收并处理请求,然后把请求数据回传回到客户端,客户端用于读取数据、关闭连接、最后结束交互

2、服务端socket模块使用步骤:

      

 1 import socket
 2 
 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 4 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  #
 5 phone.bind(('127.0.0.1',8080))    #绑定(主机,端口号)到套接字
 6 
 7 phone.listen(5)    #开始TCP监听
 8 
 9 conn,client_addr=phone.accept()  #被动接受TCP客户的连接,(阻塞式)等待连接的到来
10 
11 client_data=conn.recv(1024)   # 接收TCP数据 最大1024字节
12 conn.send(client_data.upper())   #发送TCP数据
13 
14 
15 conn.close()     #关闭TCPl连接
16 
17 phone.close()    #关闭套接字
View Code

3、客户端socket模块使用步骤:

 1 import socket
 2 
 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 4 phone.connect(('127.0.0.1',8080))   #连接服务端的ip+port
 5 
 6 
 7 msg=input('>>:').strip()
 8 
 9 phone.send(msg.encode('utf-8'))   #向服务端发送信息
10 server_data=phone.recv(1024)     #接收服务端的信息
11 
12 
13 phone.close()   #关闭连接
View Code

4、socket模块是基于TCP或UDP协议实现的,由于TCP协议是流式数据,所以基于tcp协议的socket会出现粘包现象,解决粘包现象需要使用  struct模块。

      struct模块的用途:把一个类型,如数字,转成固定长度的bytes

                   使用方法:a=struct.pack('i',123123123123)   # 将123123123123装换成4个bytes长度;

                                    stauct.unpack('i',a)[0]     #提取123123123123

         详细类型转换如图:

        

    处理粘包问题:

          我们可以把报头做成字典,字典里包含将要发送的真实数据的详细信息,然后json序列化,然后用struck将序列化后的数据长度打包成4个字节(4个自己足够用了)

         发送时:先发报头长度

                      再编码报头内容然后发送

                      最后发真实内容

         接收时:先手报头长度,用struct取出来

                       根据取出的长度收取报头内容,然后解码,反序列化

                       从反序列化的结果中取出待取数据的详细信息,然后去取真实的数据内容

   

 1 import socket,struct,json
 2 import subprocess
 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 4 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
 5 
 6 phone.bind(('127.0.0.1',8080))
 7 
 8 phone.listen(5)
 9 
10 while True:
11     conn,addr=phone.accept()
12     while True:
13         cmd=conn.recv(1024)
14         if not cmd:break
15         print('cmd: %s' %cmd)
16 
17         res=subprocess.Popen(cmd.decode('utf-8'),
18                              shell=True,
19                              stdout=subprocess.PIPE,
20                              stderr=subprocess.PIPE)
21         err=res.stderr.read()
22         print(err)
23         if err:
24             back_msg=err
25         else:
26             back_msg=res.stdout.read()
27 
28 
29         conn.send(struct.pack('i',len(back_msg))) #先发back_msg的长度
30         conn.sendall(back_msg) #在发真实的内容
31 
32     conn.close()
33 
34 服务端(自定制报头)
服务端代码
 1 #_*_coding:utf-8_*_
 2 import socket,time,struct
 3 
 4 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 5 res=s.connect_ex(('127.0.0.1',8080))
 6 
 7 while True:
 8     msg=input('>>: ').strip()
 9     if len(msg) == 0:continue
10     if msg == 'quit':break
11 
12     s.send(msg.encode('utf-8'))
13 
14 
15 
16     l=s.recv(4)
17     x=struct.unpack('i',l)[0]
18     print(type(x),x)
19     # print(struct.unpack('I',l))
20     r_s=0
21     data=b''
22     while r_s < x:
23         r_d=s.recv(1024)
24         data+=r_d
25         r_s+=len(r_d)
26 
27     # print(data.decode('utf-8'))
28     print(data.decode('gbk')) #windows默认gbk编码
29 
30 客户端(自定制报头)
客户端代码

 

  

posted @ 2017-08-24 14:11  王之迷惑  阅读(284)  评论(0编辑  收藏  举报