PythonNet_02_bj

前情回顾

1.osi七层模型是什么?
2.三次握手和四次挥手
3.tcp和udp的区别

网络概念 : 主机 端口 ip

套接字 : 网络编程的一种方式
流式套接字 —》 tcp
数据报套接字 --》udp

tcp服务端
socket()—>bind()—>listen()—>accept()—>recv()/send()—>close()


In [1]: import socket

In [2]: s = socket.socket()

In [3]: dir(s) # 查看模块下所有包含函数

In [4]: help(s.accept) # 查看函数说明文档

recv() 特性
1. 如果连接双方断开连接,则recv会立即结束阻塞返回空字符串,
双方连接时recv才能保持阻塞
2. 当接收缓冲区为空的时候会阻塞
3. 如果recv一次接收不完缓存去内容,下一次会继续接收

BrokenPipeError: 管道破裂异常
连接的双方如果有一方不存在,另一方还在企图方式内容时出现此异常

send()特性
1. 如果一端不存在,另一端还在试图send操作时会产生BrokenPipeError异常
2. 当发送缓冲区慢的时候会阻塞

网络收发缓冲区
* 发送和接收消息均先放到缓冲区中,在进行处理
即 recv和send实际是从缓冲区接收内容,向缓冲区发送消息

tcp粘包

产生原因:
tcp传输中以字节流的方式发送内容,发送的消息之间没有明显的边界,
此时如果发送和接收速度不匹配就会产生粘包

影响 : 如果每次发送的内容表示一个独立的意思此时可能需要处理粘包。
如果发送的内容本身就是连续的整体,此时不需要处理粘包

如何处理:
1.每次发送后加一个结尾标志
2.发送一个数据结构
3.每次发送中间有一个短暂的延迟

基于udp的服务端
1.创建套接字 —》 数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)

2.绑定服务端地址
sockfd.bind()

3.消息的收发
data,addr = recvfrom(buffersize)
功能 : 接收UDP消息
参数 : 每次最多接收消息的大小
返回值 : 接收到的内容
接收到的消息的发送者

  • recvfrom 一次接收一个数据包,如果数据包超出了一次能够接收的大小
    则会丢失没有收到的内容

sendto(data,addr)
功能 : udp发送消息
参数 : data 要发送的内容 bytes
addr 消息要发送给谁
返回值 : 发送的字节

4.关闭套接字
sockfd.close()

cookie :
sys.argv
功能 : 获取来自命令行的参数,形成一个列表
argv[0]是命令本身 其他内容默认以空格分割放到列表中

02_argv.py

import sys
print(sys.argv)

tarena@tedu:~$ python3 argv.py hello world
[‘argv.py’, ‘hello’, ‘world’]
tarena@tedu:~$ python3 argv.py “hello world”
[‘argv.py’, ‘hello world’]
tarena@tedu:~$ python3 argv.py 192.168.1.1 8888
[‘argv.py’, ‘192.168.1.1’, ‘8888’]

udp_server.py

from socket import *
import sys

#从命令行输入IP和端口
HOST = sys.argv[1] # 在argv[1]的地方输入IP
PORT = int(sys.argv[2]) # 在argv[2]的地方输入端口
#要访问的服务端地址
ADDR = (HOST,PORT) # 元组

#创建数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)

#绑定地址
sockfd.bind(ADDR)

#收发消息
while True:
# 等待接收消息
data,addr = sockfd.recvfrom(1024)
print(“Receive from %s:%s”%(addr,data.decode()))
sockfd.sendto(‘收到你的消息’.encode(),addr)

sockfd.close()

tarena@tedu:~$ python3 03_udp_server.py 127.0.0.1 8888
Receive from (‘127.0.0.1’, 34212):hello
Receive from (‘127.0.0.1’, 34212):nihao

from socket import *
import sys

测一下列表的长度,看IP和端口是否忘输入

if len(sys.argv) < 3:
print(’’’
argv is error!!
input as
python3 udp_client.py 127.0.0.1 8888
‘’’)
raise
HOST = sys.argv[1]
PORT = int(sys.argv[2])
#要访问的服务端地址
ADDR = (HOST,PORT)

#创建套接字
sockfd = socket(AF_INET,SOCK_DGRAM)

while True:
data = input(“消息:”)
if not data:
break
# 发送消息
sockfd.sendto(data.encode(),ADDR)
data,addr = sockfd.recvfrom(1024)
print(“从服务器收到:”,data.decode())
sockfd.close()

tarena@tedu:~$ python3 03_udp_client.py 127.0.0.1 8888
消息:hello
从服务器收到: 收到你的消息
消息:nihao
从服务器收到: 收到你的消息
消息:

tcp流式套接字和udp数据报套接字使用区别

  1. 流式套接字采用字节流的方式传输,而数据报套接字以数据包形式传输
  2. tcp会产生粘包现象,udp不会
  3. tcp编程保证传输的可靠性,udp则不保证
  4. tcp需要listren accept ,udp不需要
  5. tcp使用recv send进行消息收发,udp使用recvfrom和sendto

补充:
sendall()
功能参数: 同send
返回值 : 发送成功返回None 发送失败返回异常

In [1]: import socket

In [2]: dir(socket)

In [2]: s = socket.socket()

In [3]: dir(s) # 查看模块下所有包含函数

In [4]: help(s.accept) # 查看函数说明文档

套接字对象
(s表示一个套接字对象)

s.fileno()
功能 : 获取套接字的文件描述符
文件描述符 :每一个IO 事件操作系统都会分配一个不同的正数与之匹配,
该正数即为此IO操作的文件描述符
sys.stdin 0 标准输入
sys.stdout 1 标准输出
sys.stderr 2 标准错误

In [1]: import socket

In [2]: s = socket.socket()

In [3]: s.fileno()
Out[3]: 6

In [4]: f = open(‘abc’,‘w’)

In [6]: f.fileno()
Out[6]: 7

In [7]: import sys

In [9]: sys.stdin.fileno()
Out[9]: 0

In [10]: sys.stdout.fileno()
Out[10]: 1

In [11]: sys.stderr.fileno()
Out[11]: 2

s.type : 获取套接字类型
s.family: 地址类型

In [1]: import socket

In [2]: s = socket.socket()

In [12]: s.type
Out[12]: <SocketKind.SOCK_STREAM: 1>

In [13]: s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

In [14]: s.type
Out[14]: <SocketKind.SOCK_DGRAM: 2>

04_sock_attr.py

s.getsockname()
功能 : 获取套接字绑定的地址

s.getpeername()
功能 : 用户连接套接字,获取连接端的地址

from socket import *

s = socket()

#设置套接字选项 让端口立即释放(一旦发现网络断开,
#操作系统内核不会在保留一段时间,断开立即释放)
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

print(s.getsockopt(SOL_SOCKET,SO_REUSEADDR))

#文件描述符
print(s.fileno())
#套接字类型
print(s.type)
#地址族类型
print(s.family)

s.bind((‘172.60.50.50’,8888))

#获取套接字绑定地址
print(s.getsockname())

s.listen(5)

connfd,addr = s.accept()

#获取connfd链接的客户端地址
print(connfd.getpeername())

data = connfd.recv(1024)
print(data)

s.close()

tarena@tedu:~$ python3 04_sock_attr.py
1
3
SocketKind.SOCK_STREAM
AddressFamily.AF_INET
(‘127.0.0.1’, 8800)
(‘127.0.0.1’, 52214)
b’hello\r\n’

tarena@tedu:~$ telnet 127.0.0.1 8800
Trying 127.0.0.1…
Connected to 127.0.0.1.
Escape character is ‘^]’.
hello
Connection closed by foreign host.

s.setsockopt(level,optname,value)
功能 : 设置套接字选项 丰富修改原有套接字功能
参数: level : 设置选项的类型
IPPROTP_TCP IPPROTO_IP
SOL_SOCKET
optname: 选项类型中的子选项

	value : 为选定的选项设置值

s.getsockopt(level,optname)
功能 : 获取套接字选项值
参数: level : 获取选项的类型
IPPROTP_TCP IPPROTO_IP
SOL_SOCKET
optname: 选项类型中的子选项
返回值 : 获取到的值

udp套接字应用之广播

一点发送多点接收
目标地址 :广播地址 一个网段内最大的地址
172.60.50.255

cookie
format()
功能 : 字符串属性函数 用来组合字符串

In [1]: s = “hello,{}”.format(“Jame”)

In [2]: s
Out[2]: ‘hello,Jame’

In [3]: s = “hello,{} {}”.format(“Jame”,“Tom”)

In [4]: s
Out[4]: ‘hello,Jame Tom’

In [5]: s = “hello,{1} {0}”.format(“Jame”,“Tom”)

In [6]: s
Out[6]: ‘hello,Tom Jame’

KeyboardInterrupt:从键盘输入中断异常
SyntaxError:语法错误

#broadcast_send.py
from socket import *
from time import sleep

#广播地址
dest = (‘172.60.50.255’,9999)

#创建数据报套接字
s = socket(AF_INET,SOCK_DGRAM)

#设置套接字可以发送接收广播
s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)

while True:
#每间隔2秒发送一次
sleep(2)
s.sendto(“加油,比利时!!”.encode(),dest)

s.close()

#05_broadcast_recv.py
from socket import *

#创建数据报套接字
s = socket(AF_INET,SOCK_DGRAM)

#设置可以接收广播
s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)

#固定端口号
s.bind((’’,9999))

while True:
try:
#接收消息
msg,addr = s.recvfrom(1024)
print(“从{}获取信息:{}”.
format(addr,msg.decode()))
except (KeyboardInterrupt,SyntaxError):
raise
except Exception as e:
print(e)
s.close()

广播风暴:占用大量的带宽造成网络拥塞

tcp应用之 http传输

HTTP协议 —》 超文本传输协议

用途 : 编写基于http协议的数据传输程序
网站中浏览器端获取网页的过程

将想要获取的内容,以http协议的格式发送给服务端,服务端根据格式
进行解析获取到真实需求,将结果以http协议的格式回复给客户端

特点 :

  1. 应用层协议 ,传输层使用tcp服务
  2. 简单,灵活,和多中语言对接方便
  3. 无状态的协议 即不记录用户使用过程中传递的内容
  4. http1.1 支持持久连接

http请求 (Request)
请求格式:

请求行 具体的请求类别
GET / HTTP/1.1
请求种类 请求内容 协议版本

请求头 对请求新的的具体描述
Accept: text/html
以键值对的格式对信息进行具体描述

空行
请求体 具体的请求参数或者提交内容

请求类型:
GET 获取网络资源
POST 提交一定的附加数据,得到返回结果
HEAD 获取响应头
PUT 更新服务器资源
DELETE 删除服务器次元
CONNECT
TRACE 用于测试
OPTIONS 获取服务器性能

HTTP响应 (Response)

响应格式:

响应行 反馈具体的响应情况
HTTP/1.1 200 OK
版本 响应码 附加信息

响应头 对响应的具体描述
Accept-Ranges: bytes
以键值对方式给出响应信息的具体描述

空行
响应体 将客户想要的内容进行返回

响应码种类
1xx 提示信息,表示请求已经接受
2xx 响应成功
3xx 响应需要重定向
4xx 客户端错误
5xx 服务端错误

200 成功
404 请求内容不存在
401 没有访问权限
500 服务器发生未知错误
503 服务器暂时不能执行

要求 : 什么是http协议
请求格式和每部分的功能
响应格式和每部分功能
http请求和响应的流程

作业 : 通过流式套接字完成一个文件的发送
将一个文件从客户端发送给服务端或者从服务端发送给客户端均可

01_send_file.py

from socket import *

s = socket()
s.bind((‘127.0.0.1’,8888))
s.listen(5)

c,addr = s.accept()
print(“Connect from”,addr)

f = open(‘file.jpg’,‘rb’)

while True:
data = f.read(1024)
if not data:
break
c.send(data)
f.close()
c.close()
s.close()

01_recv_file.py

from socket import *

s = socket()
s.connect((‘127.0.0.1’,8888))

f = open(‘file_recv.jpg’,‘wb’)

while True:
data = s.recv(1024)
if not data:
break
f.write(data)

f.close()
s.close()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值