python之day9(socket)

今日重点socket网络编程:

1,tcp/ip简介:

2,socket简单应用模型:

3,socket单用户模式扩展:

4,socketserver实例:

首先记录一个在day6时没有记录的知识点:

百分比的应用:

import sys
import time

def view_bar(num, total):
    rate = float(num) / float(total)
    rate_num = int(rate * 100)
    r = ‘\r%d%%‘ % (rate_num, )
    sys.stdout.write(r)
    sys.stdout.flush()

if __name__ == ‘__main__‘:
    for i in range(0, 101):
        time.sleep(0.1)
        view_bar(i, 100)

进入主要内容:

一,tcp/ip

    osi7层结构以及具体作用。

    物理层:电缆,双绞线,无线电波

    链路层(网卡):ethernet通用协议---》找到唯一的mac地址

    网络层:IP 找到了子网中唯一的标识。

    传输层:tcp,udp,port 规定传输协议以及端口号。

    tcp/ip基本模型

二,socket简单应用模型:

    socket的所在位置。

    整个的socket交流过程。

socket要点提示:

1.基于python3.5.2版本的socket只能收发字节(python2.7可以发送str)
2.退出只在客户端退出就ok了
3.s.accept()和s.recv()是阻塞的(基于链接正常)
4.listen(n) n代表:能挂起的链接数,如果n=1,代表可以链接一个,挂起一个,第三个拒绝
5.服务端出现端口冲突:修改监听端口号
6.服户端:1.send #数据长度
              4.recv #收到确认信息,开始下一步发送

send

客户端:2.recv #获取数据长度
             3.send #发送确认信息

recv #循环接收

基础socket程序:

 1 import socket
 2 ip_port=(‘127.0.0.1‘,9999)
 3 #买手机
 4 s=socket.socket()
 5 #买手机卡
 6 s.bind(ip_port)
 7 #开机
 8 s.listen(5)
 9 #等待电话
10 while True:
11     conn,addr=s.accept()
12     #收消息
13     while True:
14         try:
15             recv_data=conn.recv(1024)
16             if len(recv_data) == 0:break
17             # print(‘--------------------‘,type(recv_data))
18             #发消息
19             send_data=recv_data.upper()
20             print(send_data)
21             conn.send(send_data)
22         except Exception:
23             break
24     #挂电话t
25     conn.close()

server1

 1 #!/usr/bin/env  python
 2 # -*- coding: UTF-8 -*-
 3 # Author: Aaron Shen
 4
 5 import socket
 6 ip_port=(‘127.0.0.1‘,9999)
 7 #买手机
 8 s=socket.socket()
 9 #拨号
10 s.connect(ip_port)
11 #发送消息
12 while True:
13     send_data=input(">>: ").strip()
14     if send_data == "exit": break
15     if len(send_data) == 0:continue
16     s.send(bytes(send_data,encoding=‘utf8‘))
17
18
19     #收消息
20     recv_data=s.recv(1024)
21     print(str(recv_data,encoding=‘utf8‘))
22 #挂电话
23 s.close()

client1

三,socket单用户模式扩展:

关于执行系统命令,以及粘包问题解决思想:

执行系统命令 用到subprocess 模块 .Popen方法 参数跟(系统命令,shell=True,stdout = subprocess.PIPE, stderr = subprocess.PIPE)

粘包问题产生的原因:

由于发送端的字节数超过了接收端一次性可接收的数量,到时一次无法将发送端的数据全部接收完,再继续执行命令是会继续进行发送,造成粘包。

解决办法:

首先就是要有一下循环的思想,只要没接收完就一直接收。因此我们要知道发送包data的具体大小。

其次我们要先将data的大小发送给接收端。

然后接收端回复Ok我收到了发送端要发送多大的包给我,我会根据这个包的大小进行循环接收,接收完就不再接收。

最后发送端开始发送数据,接收端接收知道接收完成。

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Alex Lire
 4 import socket
 5 import subprocess #导入执行命令模块
 6 ip_port=(‘127.0.0.1‘,9999) #定义元祖
 7 #买手机
 8 s=socket.socket()  #绑定协议,生成套接字
 9 s.bind(ip_port)    #绑定ip+协议+端口:用来唯一标识一个进程,ip_port必须是元组格式
10 s.listen(5)        #定义最大可以挂起胡链接数
11 #等待电话
12 while True:  #用来重复接收新的链接
13     conn,addr=s.accept()   #接收客户端胡链接请求,返回conn(相当于一个特定胡链接),addr是客户端ip+port
14     #收消息
15     while True: #用来基于一个链接重复收发消息
16             try: #捕捉客户端异常关闭(ctrl+c)
17                 recv_data=conn.recv(1024) #收消息,阻塞
18                 if len(recv_data) == 0:break #客户端如果退出,服务端将收到空消息,退出
19
20                 #发消息
21                 p=subprocess.Popen(str(recv_data,encoding=‘utf8‘),shell=True,stdout=subprocess.PIPE) #执行系统命令,windows平
22                                                                                                       # 台命令的标准输出是gbk编码,需要转换
23                 res=p.stdout.read()   #获取标准输出
24                 if len(res) == 0:   #执行错误命令,标准输出为空,
25                     send_data=‘cmd err‘
26                 else:
27                     send_data=str(res,encoding=‘gbk‘)  #命令执行ok,字节gbk---->str---->字节utf-8
28
29                 send_data=bytes(send_data,encoding=‘utf8‘)
30
31
32                 #解决粘包问题
33                 ready_tag=‘Ready|%s‘ %len(send_data)
34                 conn.send(bytes(ready_tag,encoding=‘utf8‘)) #发送数据长度
35                 feedback=conn.recv(1024)  #接收确认信息
36                 feedback=str(feedback,encoding=‘utf8‘)
37
38                 if feedback.startswith(‘Start‘):
39                     conn.send(send_data)  #发送命令的执行结果
40             except Exception:
41                 break
42     #挂电话
43     conn.close()

进阶socket_server

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Alex Li
 4 import socket
 5 ip_port=(‘127.0.0.1‘,9999)
 6 #买手机
 7 s=socket.socket()
 8 #拨号
 9 s.connect(ip_port)  #链接服务端,如果服务已经存在一个好的连接,那么挂起
10
11 while True:        #基于connect建立的连接来循环发送消息
12     send_data=input(">>: ").strip()
13     if send_data == ‘exit‘:break
14     if len(send_data) == 0:continue
15     s.send(bytes(send_data,encoding=‘utf8‘))
16
17     #解决粘包问题
18     ready_tag=s.recv(1024) #收取带数据长度的字节:Ready|9998
19     ready_tag=str(ready_tag,encoding=‘utf8‘)
20     if ready_tag.startswith(‘Ready‘):#Ready|9998
21         msg_size=int(ready_tag.split(‘|‘)[-1])  #获取待接收数据长度
22     start_tag=‘Start‘
23     s.send(bytes(start_tag,encoding=‘utf8‘)) #发送确认信息
24
25     #基于已经收到的待接收数据长度,循环接收数据
26     recv_size=0
27     recv_msg=b‘‘
28     while recv_size < msg_size:
29         recv_data=s.recv(1024)
30         recv_msg+=recv_data
31         recv_size+=len(recv_data)
32         print(‘MSG SIZE %s RECE SIZE %s‘ %(msg_size,recv_size))
33
34     print(str(recv_msg,encoding=‘utf8‘))
35     #挂电话
36 s.close()

进阶socket_client

四,socketserver实例:

  这部分是alex大拿老师讲的,基本上没听懂,呵呵,主要靠课下重新读代码,重新构思的。

  首先说一下socketserver与普通socket的区别:

  普通socket所有点链路(conn)都是单通道的,只能一个客户端占用。服务端也是一对一进行相应。如果还有别的客户端要访问就要排队等待,直到之前的客户端退出后才可以与服务端进行交互。

  

  socketserver 使用socketserver模块(2.7头字母要进行大写),继承了socketserver.BaseRequestHandler这个类,我们用的时候必须使用 handle这个函数。他的特点就是可以完成一对多的相应。

   基本程序构建:

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Alex Li
 4
 5
 6 #!/usr/bin/env python
 7 # -*- coding:utf-8 -*-
 8 #import SocketServer
 9 import socketserver
10
11 class MyServer(socketserver.BaseRequestHandler):
12     def handle(self):
13         # print self.request,self.client_address,self.server
14         self.request.sendall(bytes(‘欢迎致电 10086,请输入1xxx,0转人工服务.‘,encoding="utf-8"))
15         while True:
16             data = self.request.recv(1024)
17             print("-->",len(data))
18             if len(data) == 0:break
19             print("[%s] says:%s" % (self.client_address,data.decode() ))
20             self.request.sendall(data.upper())
21
22 if __name__ == ‘__main__‘:
23     server = socketserver.ThreadingTCPServer((‘127.0.0.1‘,8009),MyServer)
24     server.serve_forever()

socket_server

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Alex Li
 4
 5 import socket
 6 ip_port=(‘192.168.11.58‘,8009)
 7 #买手机
 8 s=socket.socket()
 9 #拨号
10 s.connect(ip_port)
11 #发送消息
12 welcome_msg = s.recv(1024)
13 print("from server:",welcome_msg.decode())
14 while True:
15     send_data=input(">>: ").strip()
16     if len(send_data) == 0:continue
17     s.send(bytes(send_data,encoding=‘utf8‘))
18     #收消息
19     recv_data=s.recv(1024)
20     print(str(recv_data,encoding=‘utf8‘))
21     #挂电话
22 s.close()

socket_client

  通过socket 远程执行命令(通过客户端发送命令到服务端并执行)

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Alex Li
 4
 5
 6 #!/usr/bin/env python
 7 # -*- coding:utf-8 -*-
 8 #import SocketServer
 9 import socketserver
10 import subprocess
11 class MyServer(socketserver.BaseRequestHandler):
12     def handle(self):
13         # print self.request,self.client_address,self.server
14         self.request.sendall(bytes(‘欢迎致电 10086,请输入1xxx,0转人工服务.‘,encoding="utf-8"))
15         while True:
16             data = self.request.recv(1024)
17             if len(data) == 0:break
18             print("[%s] says:%s" % (self.client_address,data.decode() ))
19             #self.request.sendall(data.upper())
20             cmd = subprocess.Popen(data.decode(),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
21             cmd_res =cmd.stdout.read()
22             if not cmd_res:
23                cmd_res = cmd.stderr.read()
24             if len(cmd_res) == 0: #cmd has not output
25                cmd_res = bytes("cmd has output",encoding="utf-8")
26             self.request.send(cmd_res )
27
28
29 if __name__ == ‘__main__‘:
30     server = socketserver.ThreadingTCPServer((‘0.0.0.0‘,8009),MyServer)
31     server.serve_forever()

com_server

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Alex Li
 4
 5 import socket
 6 ip_port=(‘192.168.11.58‘,8009)
 7 #买手机
 8 s=socket.socket()
 9 #拨号
10 s.connect(ip_port)
11 #发送消息
12 welcome_msg = s.recv(1024)
13 print("from server:",welcome_msg.decode())
14 while True:
15     send_data=input(">>: ").strip()
16     if len(send_data) == 0:continue
17     s.send(bytes(send_data,encoding=‘utf8‘))
18     #收消息
19     recv_data=s.recv(1024)
20     print(str(recv_data,encoding=‘utf8‘))
21     #挂电话
22 s.close()

com_client

  通过socket进行ftp 上传操作(通过客户端发送指令,上传到服务器端)

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Alex Li
 4
 5
 6 #!/usr/bin/env python
 7 # -*- coding:utf-8 -*-
 8 #import SocketServer
 9 import socketserver,json
10 class MyServer(socketserver.BaseRequestHandler):
11     def handle(self):
12         # print self.request,self.client_address,self.server
13         self.request.sendall(bytes(‘欢迎致电 10086,请输入1xxx,0转人工服务.‘,encoding="utf-8"))
14         while True:
15             data = self.request.recv(1024)                  #接收要进行操作的基本信息,包括动作,文件路径以及文件名,文件大小
16             if len(data) == 0:break
17             print("data", data)
18             print("[%s] says:%s" % (self.client_address,data.decode() ))
19
20             task_data = json.loads( data.decode()  )        #接收到一个json格式的字典
21             task_action = task_data.get("action")           #获取字典的中动作的值
22             if hasattr(self, "task_%s"%task_action):        #反射到本程序的下面的函数,查看是否存在。如果存在
23                func = getattr(self,"task_%s" %task_action)  #获取函数
24                func(task_data)                                     #执行函数,同时参数就是那个字典
25             else:
26                print("task action is not supported",task_action)
27
28     def task_put(self,*args,**kwargs):
29         print("---put",args,kwargs)
30         filename = args[0].get(‘filename‘)          #文件名就等于task_data.get(‘filename‘)
31         filesize = args[0].get(‘file_size‘)         #文件大小就等于task_data.get(‘file_size‘)
32         server_response = {"status":200}            #准备工作都准备好后,给客户端发一个确认
33         self.request.send(bytes( json.dumps(server_response), encoding=‘utf-8‘  ))      #发送确认
34         f = open(filename,‘wb‘)                     #打开文件
35         recv_size = 0                                #未开始接收,因此接收大小是 0
36         while recv_size < filesize:                  #如果接收大小小于文件大小就是一直循环
37             data = self.request.recv(4096)            #开始接收
38             f.write(data)                               #写入文件
39             recv_size += len(data)                      #增加大小
40             print(‘filesize: %s  recvsize:%s‘ % (filesize,recv_size))           #展示进度
41         print("file recv success")                      #循环结束,完成接收
42         f.close()
43
44 if __name__ == ‘__main__‘:
45     server = socketserver.ThreadingTCPServer((‘0.0.0.0‘,8009),MyServer)
46     server.serve_forever()

ftp_server

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # Author:Alex Li
 4
 5 import socket
 6 import os ,json
 7 ip_port=(‘192.168.11.150‘,8009)                     #要访问的服务端IP以及端口
 8 #买手机
 9 s=socket.socket()                                      #生成套接字s
10 #拨号
11 s.connect(ip_port)                                      #连接服务和端口
12 #发送消息
13 welcome_msg = s.recv(1024)                              #获取服务端相应
14 print("from server:",welcome_msg.decode())             #打印获取的服务端欢迎语
15 while True:                                             #循环交互
16     send_data=input(">>: ").strip()
17     if len(send_data) == 0:continue                     #如果发送为空就重新发送
18
19     cmd_list = send_data.split()                        #将命令进行分割 [put  test.txt]
20     if len(cmd_list) <2:continue                        #如果小于2个元素就重新输入,命令是不完整的
21     task_type = cmd_list[0]                               #第一个是命令 put, 第二个是文件路径
22     if task_type == ‘put‘:                              #如果是 put
23         abs_filepath = cmd_list[1]                       #第二个就是文件路径
24         if os.path.isfile(abs_filepath):                   #如果文件存在
25             file_size = os.stat(abs_filepath).st_size       #获取文件大小
26             filename = abs_filepath.split("\\")[-1]         #获取文件名
27             print(‘file:%s size:%s‘ %(abs_filepath,file_size))
28             msg_data = {"action":"put",
29                         "filename":filename,
30                         "file_size":file_size}             #写成字典包括动作,文件名,文件大小
31
32             s.send(  bytes(json.dumps(msg_data),encoding="utf-8")  )        #将字典整合成json发送给服务端(明确要上传的信息)
33             server_confirmation_msg = s.recv(1024)                           #接收服务端发送的确认信息。
34             confirm_data = json.loads(server_confirmation_msg.decode())      #获取确认信息,服务端发来的信息也是json封装的字典
35             if confirm_data[‘status‘] ==200:                                #如果是200 确认成功
36
37                 print("start sending file ",filename)
38                 f = open(abs_filepath,‘rb‘)                                 #二进制打开要上传的文件
39                 for line in f:                                              #逐行循环
40                     s.send(line)                                             #上传到服务端
41
42                 print("send file done ")
43
44         else:
45             print("\033[31;1mfile [%s] is not exist\033[0m" % abs_filepath)
46             continue
47     else:
48         print("doesn‘t support task type",task_type)
49         continue
50     #s.send(bytes(send_data,encoding=‘utf8‘))
51     #收消息
52     recv_data=s.recv(1024)
53     print(str(recv_data,encoding=‘utf8‘))
54     #挂电话
55 s.close()

ftp_client

时间: 2024-08-03 15:31:58

python之day9(socket)的相关文章

python基础之socket编程

python基础之socket编程   一 TCP/IP五层模型 在每一层都工作着不同的设备,比如我们常用的交换机就工作在数据链路层的,一般的路由器是工作在网络层的. 在每一层实现的协议也各不同,即每一层的服务也不同.下图列出了每层主要的协议. 各层功能 注明:ARP和RAPR两个到底属于哪一层呢? 由于IP协议使用了ARP协议,所以经常把ARP协议划到网络层,但是ARP协议是为了从网络层使用的IP地址解析出在数据链路层使用的MAC地址,所以有些地方也把ARP协议划分到数据链路层,但是一般情况下

Python 3.5 socket OSError: [Errno 101] Network is unreachable

/******************************************************************************** * Python 3.5 socket OSError: [Errno 101] Network is unreachable * 说明: * 在网络状态一切正常的时候没有出现这个问题,当出现比较长时间的网络连接中断 * 的情况下,会出现这个现象,try...except...解决. * * 2017-3-1 深圳 南山平山村 曾剑锋

python基础之socket

---引入 Socket的英文原义是“孔”或“插座”,在Unix的进程通信机制中又称为‘套接字’.套接字实际上并不复杂,它是由一个ip地址以及一个端口号组成.Socket正如其英文原意那样,像一个多孔插座.一台主机犹如布满各种插座(ip地址)的房间,每个插座有很多插口(端口),通过这些插口接入电线(进程)我们可以烧水,看电视,玩电脑…… 应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 套接字的作用之一就是用来区分不同应用进程,当某个进程绑定了本机ip的某个端口,那么所有传送

Python 基础之socket编程(二)

Python 基础之socket编程(二) 昨天只是对socket编程做了简单的介绍,只是把socket通信的框架搭建起来,要对其中的功能进行进一步的扩充,就来看看今天的料哈! 一.基于tcp的套接字 1. tcp的服务端 ss = socket() #创建服务器套接字 ss.bind() #把地址绑定到套接字 ss.listen() #监听链接 inf_loop: #服务器无限循环 cs = ss.accept() #接受客户端链接 comm_loop: #通讯循环 cs.recv()/cs.

python基础之socket与socketserver

---引入 Socket的英文原义是"孔"或"插座",在Unix的进程通信机制中又称为'套接字'.套接字实际上并不复杂,它是由一个ip地址以及一个端口号组成.Socket正如其英文原意那样,像一个多孔插座.一台主机犹如布满各种插座(ip地址)的房间,每个插座有很多插口(端口),通过这些插口接入电线(进程)我们可以烧水,看电视,玩电脑-- 应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 套接字的作用之一就是用来区分不同应用进程,当某个进

python模块之socket

43.python模块之socket: Python在网络通讯方面功能强大,学习一下Socket通讯的基本方式 UDP通讯: Server: import socket port=8081 s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #从指定的端口,从任何发送者,接收UDP数据 s.bind(('',port)) print('正在等待接入...') while True: #接收一个数据 data,addr=s.recvfrom(1024

Python学习记录-socket编程

Python学习记录-socket编程 学习 python socket Python学习记录-socket编程 1. OSI七层模型详解 2. Python socket 3. socket()函数 4. TCP socket通信流程 5. Python Internet 模块 1. OSI七层模型详解 以上图见:http://blog.csdn.net/yaopeng_2005/article/details/7064869 其它详情可参考:socket网络基础 2. Python sock

Python 基础之socket编程(三)

python 基础之socket编程(三) 前面实现的基于socket通信只能实现什么呢?在tcp协议的通信中就是一个用户说一句,服务端给你回一句,你再给服务端说一句,服务端再给你回一句,就这样一直友好的玩耍下去了.等等,又有一个用户来了,他呢也想和和服务端进行一下交流,于是他就给服务端发送了一条消息,之后等呀等不知过了多久,任然没有等到服务端给他发挥的消息,只有什么时候他就可以和服务端愉快的玩耍了呢?这个就需要第一个用户退出和服务器的链接,此时第二个客户端才会和服务端建立起链接,此时此刻,他才

python 中的socket

python中利用socket模块来实现对各种底层通讯的封装,支持tcp/udp协议,为编制c/s类的程序提供了便利. 最常见的用法: 如ftp_server: 1 import socketserver 2 class Mysocketserver(socketserver.BaseRequestHandler): 3 def handle(self): 4 while True: 5 try: 6 self.data=self.request.recv(1024).strip() 7 pri