python之路 -- 网络编程

1.软件开发的架构

- C/S架构(需要安装应用程序使用的软件)

  c client 客户端

  s server 服务端

- B/S架构(可以通过浏览器使用的)

  b broser 浏览器

  s server 服务端

不需要额外的安装客户端了,只需要一个网址就可以访问

轻量级,使用成本低

2.tcp协议/udp协议

tcp协议
  全双工的通信协议
  建立了专门穿送数据的通道(连接),是一个长连接
  面向流的传输
  传输速率比udp协议慢
  数据安全不容易丢失
  大文件算法自己拆包编号发送
  建立连接的 三次握手
  断开连接的 四次挥手
udp协议
  是面向文件的传输,
  是一种不可靠的
  不需要建立连接,直接传送(传输通道)
  传输速率比tcp协议高
  不适合大文件的传输(文件过大会报错)

3.socket

网络编程就是如何在程序中实现两台计算机的通信,而两台计算机间的通信其实就是两个进程间的通信,进程间的通信主要通过socket(套接字)来描述ip地址(主机)和端口(进程)来实现的

socket是python中的一个内置模块

socket的使用

--使用tcp协议的socket

 1     server端-tcp_server.py
 2 import socket
 3 tcp_sk = socket.socket()    #创建客户套接字
 4 tcp_sk.bind(("127.0.0.1",8090))   #把地址,端口绑定到套接字,参数为一个元组
 5
 6 tcp_sk.listen() #监听链接(请求)
 7 conn, addr = tcp_sk.accept()    #接受客户端链接
 8 ret1 = conn.recv(1024)   #接收客户端信息,参数为这一次最接收1024个字节
 9 print(ret1)      #打印客户端信息
10 conn.send(b‘hi‘)    #向客户端发送信息,必须传一个bytes类型
11 ret2 = conn.recv(1024)
12 print(ret2.decode("utf-8"))
13 conn.send(bytes(‘吃了‘,encoding="utf-8"))
14
15 conn.close()    #关闭客户端套接字
16 tcp_sk.close()  #关闭服务器套接字
17
18
19 client端-tcp_clent.py
20 import socket
21 tcp_sk = socket.socket()
22 tcp_sk.connect((‘127.0.0.1‘,8090))
23
24 tcp_sk.send(b‘hello‘)
25 ret = tcp_sk.recv(1024)
26 print(ret)
27 tcp_sk.send(bytes("吃了吗?",encoding=‘utf-8‘))
28 ret2 = tcp_sk.recv(1024)
29 print(ret2.decode(‘utf-8‘))
30
31 tcp_sk.close()

--使用udp协议的socket

 1     server端-udp_server.py
 2 import socket
 3 sk = socket.socket(type=socket.SOCK_DGRAM)
 4 sk.bind(("127.0.0.1",8096))
 5 # 传入的IP和端口号必须是元组的形式
 6 msg,addr = sk.recvfrom(1024)
 7 print(msg.decode(‘utf-8‘))
 8 sk.sendto(b‘bye‘,addr)
 9 sk.close()
10
11
12     client端-udp_client.py
13 import socket
14 sk = socket.socket(type=socket.SOCK_DGRAM)
15 ip_port = ("127.0.0.1",8096)
16 # 传入IP_port的时候必须是元组形式
17 sk.sendto(b‘hello‘,ip_port)
18 ret,addr = sk.recvfrom(1024)
19 print(ret.decode(‘utf-8‘))
20
21 sk.close()
22
23 # udp的server不需要进行监听,也不需要建立连接
24 # 在启动服务之后只能被动的等待客服端发送消息过来
25 # 客户端发送消息的同时还需要带上地址信息
26 # 消息回复的时候,不仅需要发送消息,还需要把对方的地址填写上

注意事项:

--发送的消息必须是bytes类型的数据。注意编码encode,解码decode

--传入的IP地址、端口号必须以元组的形式传入,直接开的端口号一般在8000以后

--tcp协议不能发空消息,udp协议可以

--tcp协议会发生黏包现象,udp协议不会发生黏包现象

--使用tcp协议的socket必须先运行sever端,再运行client端。基于udp的socket不需要有运行的顺序

--一般先关闭client端,再关闭sever端

黏包问题及解决方案

1.为什么会出现黏包现象:

首先只有在tcp协议中才会出现黏包现象

是因为tcp协议是面向流的协议

在发送数据传输的过程中还有缓存机制来避免数据丢失

因此在连续发送小数据的时候,以及接收大小不符合的时候都容易出现黏包现象

本质还是因为我们在接收数据的时候不知道发送的数据的长短

2.解决黏包问题的方案:

在传输大量数据之前先高数接收端要发送的数据的大小

高跟好的解决方案:通过struct模块来定制协议



demo1,远程发送系统命令

 1 demo1,远程发送系统命令
 2 server端
 3 import socket
 4 sk = socket.socket()
 5 sk.bind((‘127.0.0.1‘,8090))
 6 sk.listen()
 7 conn,addr = sk.accept()
 8
 9 while True:
10     cmd = input(‘>>>‘)
11     if cmd == "q":
12         conn.send(b"q")
13         break
14     conn.send(cmd.encode(‘gbk‘))
15     res = conn.recv(500)
16     print(res.decode(‘gbk‘))
17
18 conn.close()
19 sk.close()
20
21 client端
22 import socket
23 import subprocess
24
25 sk = socket.socket()
26 sk.connect((‘127.0.0.1‘,8090))
27
28 while True:
29     cmd = sk.recv(1024).decode(‘gbk‘)
30     if cmd == "q":
31         break
32     res = subprocess.Popen(cmd,shell=True,
33                            stdout=subprocess.PIPE,
34                            stderr=subprocess.PIPE)
35     sk.send(res.stdout.read())
36     sk.send(res.stderr.read())
37
38 sk.close()

demo2,使用struct模块解决黏包问题

 1 demo2,使用struct模块解决黏包问题
 2 server端
 3 import socket
 4 import struct
 5
 6 sk = socket.socket()
 7 sk.bind((‘127.0.0.1‘,8090))
 8 sk.listen()
 9 conn,addr = sk.accept()
10
11 while True:
12     cmd = input(‘>>>‘)
13     if cmd == "q":
14         conn.send(b"q")
15         break
16     conn.send(cmd.encode(‘gbk‘))
17     num_by = conn.recv(4)
18     num = struct.unpack(‘i‘,num_by)[0]
19     res = conn.recv(int(num)).decode(‘gbk‘)
20     print(res)
21
22 conn.close()
23 sk.close()
24
25 client端
26 import socket
27 import subprocess
28 import struct
29
30 sk = socket.socket()
31 sk.connect((‘127.0.0.1‘,8090))
32
33 while True:
34     cmd = sk.recv(1024).decode(‘gbk‘)
35     if cmd == "q":
36         break
37     res = subprocess.Popen(cmd,shell=True,
38                            stdout=subprocess.PIPE,
39                            stderr=subprocess.PIPE)#只能读取一次,读后就没有了,类似队列
40     std_out = res.stdout.read()
41     std_err = res.stderr.read()
42     len_num = len(std_out)+len(std_err) #计算所要发送数据的长度
43     num_by = struct.pack(‘i‘,len_num)
44     sk.send(num_by)
45     sk.send(std_out)
46     sk.send(std_err)
47
48 sk.close()

demo3,实现大文件的传输

 1 server端
 2 #_*_coding:utf-8_*_
 3
 4 import socket
 5 import struct
 6 import  json
 7
 8 buffer = 1024
 9
10 sk = socket.socket()
11 sk.bind((‘127.0.0.1‘,8080))
12 sk.listen()
13 conn, addr = sk.accept()
14
15 headlen = conn.recv(4)
16 head_len = struct.unpack(‘i‘,headlen)[0]    #unpack之后得到的是一个元组
17 head_json = conn.recv(head_len).decode(‘utf-8‘)
18 head = json.loads(head_json)
19 file_size = head[‘filesize‘]
20
21 with open(head["filename"],mode="wb")as f:
22     while file_size:
23         if file_size >= buffer:
24             content = conn.recv(buffer)
25             file_size -= buffer
26             f.write(content)
27         else:
28             content = conn.recv(file_size)
29             f.write(content)
30             break
31
32 conn.close()
33 sk.close()
34
35
36 client端
37 #_*_coding:utf-8_*_
38
39 import socket
40 import os
41 import json
42 import struct
43
44 buffer = 1024
45
46 sk = socket.socket()
47 sk.connect((‘127.0.0.1‘,8080))
48
49 # 制作报头
50 head = {
51     ‘filename‘:‘04 python fullstack s9day32 struct模块补充.mp4‘,
52     ‘filepath‘:‘F:\python全栈9期视频\第一部分-基础\day32‘,
53     ‘filesize‘:‘‘
54 }
55 file_path = os.path.join(head[‘filepath‘],head[‘filename‘])
56 file_size = os.path.getsize(file_path)
57 head[‘filesize‘] = file_size
58
59 #先发送报头的大小
60 json_head = json.dumps(head)    #将报头的字典转换成字符串
61 bytes_head = json_head.encode(‘utf-8‘)  #将报头head转换成bytes类型
62 len_head = len(bytes_head)  #计算head的长度
63 head_pack = struct.pack(‘i‘,len_head)
64 sk.send(head_pack)      #先发送报头的长度
65 sk.send(bytes_head)     #再发送报头的bytes类型数据
66 with open(file_path,mode = "rb") as f:
67     while file_size:
68         if file_size >= buffer:
69             content = f.read(buffer)
70             file_size -= buffer
71             sk.send(content)
72         else:
73             content = f.read(file_size)
74             sk.send(content)
75             break
76
77 sk.close()

demo4,验证客户端的合法性

 1 demo4,验证客户端的合法性
 2 server端
 3 import socket
 4 import os
 5 import hmac
 6
 7 secret_key = b‘egg‘
 8 sk = socket.socket()
 9 sk.bind(("127.0.0.1",8066))
10 sk.listen()
11
12 def check_conn(conn):
13     msg = os.urandom(32)
14     conn.send(msg)
15     h = hmac.new(secret_key,msg)
16     digest = h.digest()
17     client_digest = conn.recv(1024)
18     return hmac.compare_digest(digest,client_digest)
19
20 conn,addr = sk.accept()
21 res = check_conn(conn)
22 if res:
23     print("合法的客户端")
24     conn.close()
25 else:
26     print("不合法的客户端")
27     conn.close()
28
29 sk.close()
30
31
32 client端
33 import socket
34 import hmac
35
36 secret_key = b‘egg‘
37
38 sk = socket.socket()
39 sk.connect((‘127.0.0.1‘,8066))
40 msg = sk.recv(1024)
41 h = hmac.new(secret_key,msg)
42 digest = h.digest()
43 sk.send(digest)
44
45 sk.close()

原文地址:https://www.cnblogs.com/aberwang/p/9355196.html

时间: 2024-09-29 18:11:20

python之路 -- 网络编程的相关文章

Python之路——网络编程

socket TCP 服务端 1 import socket 2 sk = socket.socket() 3 sk.bind(('127.0.0.1',8080)) # 绑定ip和端口号 4 sk.listen() # Enable a server to accept connections. 5 conn,addr = sk.accept() # Wait for an incoming connection. Return a new socket 6 # representing th

python高级之网络编程

python高级之网络编程 本节内容 网络通信概念 socket编程 socket模块一些方法 聊天socket实现 远程执行命令及上传文件 socketserver及其源码分析 1.网络通信概念 说到网络通信,那就不得不说TCP/IP协议簇的OSI七层模型了,这个东西当初在学校都学烂了...(PS:毕竟本人是网络工程专业出身...) 简单介绍下七层模型从底层到上层的顺序:物理层(定义物理设备的各项标准),数据链路层(mac地址等其他东西的封装),网络层(IP包头的的封装),传输层(TCP/UD

Python四大主流网络编程框架

目前Python的网络编程框架已经多达几十个,逐个学习它们显然不现实.但这些框架在系统架构和运行环境中有很多共通之处,本文带领读者学习基于Python网络框架开发的常用知识,及目前的4种主流Python网络框架:Django.Tornado.Flask.Twisted. 网络框架及MVC架构 所谓网络框架是指这样的一组Python包,它能够使开发者专注于网站应用业务逻辑的开发,而无须处理网络应用底层的协议.线程.进程等方面.这样能大大提高开发者的工作效率,同时提高网络应用程序的质量. 在目前Py

《Python学习之路 -- 网络编程》

在前面已经提到过,互联网的本质就是一堆协议,协议就是标准,比如全世界人通信的标准是英语,所有的计算机都学会了互联网协议,那么所有的计算机就可以按照统一的标准去收发信息完成通信了. 作为普通开发人员的我们,写的软件/程序都是处于应用层上的,然而,想要让软件接入互联网,就必须得通过传输层,也就是必须遵循TCP协议或者UDP协议.这是两个非常复杂的协议,如果遵循原生的协议,那么必然会大大降低效率,所以就有了socket抽象层的概念.socket是应用层与TCP/IP协议族通信的软件抽象层,它是一组接口

Python TCP通信网络编程

最近在看廖雪峰老师的基础教程(http://www.liaoxuefeng.com/),今天实现了一下简单Python的Socket的网络编程. 1. Socket网络编程 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可. 2. 客户端 大多数连接都是可靠的TCP连接.创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器.举个例子,当我们在浏览器中访问新浪时,我

Python实践之网络编程1-简单的网络请求程序

在了解python基础的语法基础上,就可以自由的去组合出自己需要各类高级功能. 由于python语言的特性,各类功能的实现都会非常快捷的. 网络变成就是python具备的高级特性之一. 需要进行网络编程首先需要了解几个模块urllib和urllib2 1.简单的访问请求 import sys,urllib,urllib2 url=input("please input the url:") url = "http://mail.126.com" #发起请求 req

python学习之网络编程基础

引入场景:客户与银行关系 银行职员负责给客户提供取钱服务,客户通过账户密码跟银行职员建立合作关系.此时银行职员就可以作为服务器,当用户A取完钱后他需要等待下一个用户的接入,用户的账号密码就是建立合作关系的凭据.------简单的客户端/服务器架构模型. 客户端/服务器网络编程过程 一:创建套接字(通信端点) AF_XXX解释:地址家族名称,AF:Address Family 基于文件套接字 AF_UNIX 基于网络套接字 AF_INET 代表ipv4  (python网络编程中常用的套接字)  

『Python』socket网络编程

Python3网络编程 '''无论是str2bytes或者是bytes2str其编码方式都是utf-8 str( ,encoding='utf-8') bytes( ,encoding='utf-8') 而在使用.encode('utf-8')时,虽然type类型是byte,但常常报错''' Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯. socket起源于UNIX,在Unix一切皆文

Python进阶之网络编程

网络通信 使用网络的目的 把多方链接在一起,进行数据传递: 网络编程就是,让不同电脑上的软件进行数据传递,即进程间通信: ip地址 ip地址概念和作用 IP地址是什么:比如192.168.1.1 这样的一些数字: ip地址的作用:用来在电脑中 标识唯一一台电脑,比如192.168.1.1:在本地局域网是唯一的. 网卡信息 查看网卡信息 Linux:ifconfig windows:ipconfig ensxx:用来与外部进行通信的网卡: lo:环回网卡,用来进行本地通信的: linux关闭/开启