python 网络编程 day02

本文介绍了Python网络编程的基础,包括TCP粘包现象、UDP服务端编程、套接字属性以及HTTP协议的请求和响应。讨论了TCP与UDP的区别,如TCP的可靠性、粘包处理,而UDP的无连接性。并提供了简单的TCP UDP服务端和客户端示例,以及HTTP请求和响应的格式。

2018.8.7

目录

tcp粘包

基于udp的服务端编程

socket模块和套接字属性

udp套接字应用---》广播

tcp应用--》http传输:

http请求(Request)

http响应(response)


day01回顾

1,osi七层模型---》四层  五层

2,三次握手,四次挥手 

3,tcp和udp区别

网络概念:主机  端口  ip  协议

  • 服务端:localhost / 127.0.0.1
  • 客户端:只是在本机启动客户端 用127.0.0.1访问

 

  • 服务端:0.0.0.0
  • 客户端:可以在本机用127.0.0.1、172.60.50.181访问,
                   局域网内用 172.60.50.181

 

  • 服务端:172.60.50.181
  • 客户端:局域网内用 172.60.50.181访问

套接字 socket

  • 流式套接字 --》 tcp 可靠地 有连接
  • 数据报套接字 --》udp  不可靠  无连接

tcp服务端

socket --> bind --> listen --> accept --> recv/send -->close


day02

recv() 特征

  • *如果连接的另一端断开连接,则recv立即返回空字符串
  • recv是从接受缓冲区取出内容,当缓冲区为空则阻塞
  • recv如果一次接受不完缓冲区内容,下次会继续接收

send() 特征

  • *如果发送的另外一段不存在则会产生pipe Broken
  • recv是向发送缓冲区发送内容,当缓冲区为满阻塞

网络收发缓冲区

  • 在内存中开辟的区域,用作发送和接受的缓冲
  • 协调数据的收发(接受和处理)速度
  • 减少和磁盘的交互

sendall(data)

  • 功能:tcp套接字发送消息
  • 参数:同send
  • 返回值:如果发送成功返回None

tcp粘包

  1. 产生原因:
    tcp传输以字节流的方式发送消息,消息之间没有边界
    发送比接收的速度快,此时如果发送和接收速度不匹配就会产生粘包
  2. 影响:对每次发送的内容是一个独立的意思需要单独识别,如果发送的内容本身就是连续的整体,此时不需要处理粘包
  3. 如何处理
    1,每次发送后加一个结尾标志
    2,发送一个数据结构
    3,每次发送有一个间隔

基于udp的服务端编程

  1. 创建套接字
    sockfd = socket(AF_INET,SOCK_DGRAM)
  2. 绑定地址
    sockfd.bind()
  3. 消息的收发
    1. 接收
      1. 格式:data,addr = sockfd.recvfrom(buffersize)
      2. 功能:接收UDP消息
      3. 参数:每次最多接收消息的大小,字节
      4. 返回值:data接收到的内容
                      addr 消息发送方的地址
      5.  recvfrom 一次接收一个数据包,如果数据包超出了一次能够接收的大小则会丢失没有收到的内容
    2. 发送
      1. 格式sockfd.sendto(data,addr)
      2. 功能 : udp发送消息
      3. 参数 : data 要发送的内容 bytes 
                     addr 消息要发送给谁(目标地址)
      4. 返回值 : 发送的字节数
  4. 关闭套接字 
    sockfd.close()

    服务器:

    #utip.py
    
    from socket import *
    
    HOST = '0.0.0.0'
    PORT = 8888
    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()

    客户端:

    #namen.py
    
    from socket import *
    import sys
    
    #命令行输入服务器地址
    if len(sys.argv) < 3:
        print('''
            argv is error !!
            start 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()

    运行结果:




     

cookie:

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

  示例:

import sys
print(sys.argv)

python3 namen.py
['namen.py']

python3 namen.py 1 2 hello
['namen.py', '1', '2', 'hello']


python3 namen.py 1 2 'hello 1' 2
['namen.py', '1', '2', 'hello 1', '2']

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

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

    要求:能够说出tcp,udp协议的区别和编程实现上的差异

 

socket模块和套接字属性

(s为套接字)

套接字属性

s.type:表示套接字类型

s.family:地址类型

套接字属性方法

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

  1. 功能:获取套接字的文件描述符
  2. 文件描述符:每一个IO事件操作系统都会分配一个不同的正整数与之匹配,该整数即为此IO的文件描述符
    一般是从3开始,默认0 ,1,2在下面3个套接字
  3. sys.stdin 0
  4. sys.stdout 1
  5. sys.stderr 2

s.getsockname()

  1. 功能:获取套接字绑定的地址

s.getpeername()

  1. 功能:使用accept生成的套接字调用,获取该套接字对应的客户端地址

s.setsockopt(level,optname,value)

  1. 功能:设置套接字选项
  2. 参数:level设置选项的类型   SOL_SOCKET
    可选值还有:IPPROTO_TCP  IPPROTP_IP
    optname: 选项类型中的子选项 
    value :设置的值
    e.g.:s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

s.getsockopt(level,optname) 

  1. 功能 : 获取套接字选项值 
  2. 参数: level : 获取选项的类型  SOL_SOCKET 
  3. IPPROTP_TCP IPPROTO_IP 
  4. optname: 选项类型中的子选项 
  5. 返回值 : 获取到的值 

    SQL_SOCKET对应的子选项:


    一些套接字示例:
    from socket import * 
    
    s = socket()
    
    #设置端口可立即重用
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    print(s.getsockopt(SOL_SOCKET,SO_REUSEADDR))
    
    #获取套接字类型
    print(s.type)
    #获取地址类型
    print(s.family)
    
    #文件描述符
    print(s.fileno())
    
    s.bind(('172.60.50.181',9999))
    #获取绑定地址
    print(s.getsockname())
    
    s.listen(5)
    
    c,addr = s.accept()
    
    print(c.getpeername())
    print("addr:",addr)
    
    data = c.recv(1024)
    print(data)
    
    c.close()
    s.close()

     

udp套接字应用---》广播

  1. 一点发送多点接收
    1. 目标地址 :广播地址 一个网段内最大的地址 
      172.60.50.255
    2. 广播风暴:占用大量的带宽造成网络拥塞
  2. format()
    1. 功能 : 字符串属性函数 用来组合字符串

format()示意:

#format()示例
In [3]: s = "{} is a {}".format('Tom','boy')

In [4]: s
Out[4]: 'Tom is a boy'

In [5]: s = "{1} is a {0}".format('Tom','boy')

In [6]: s
Out[6]: 'boy is a Tom'

下面是广播示例:(广播接收端)

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()

广播发送端:

from socket import * 
from time import sleep 

#设置广播地址 "<broadcast>"
dest = ('172.60.50.255',9229)

s = socket(AF_INET,SOCK_DGRAM)

#设置能够发送广播
s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)

while True:
    sleep(2)
    s.sendto("今日立秋".encode(),dest)
s.close()

 

tcp应用--》http传输:

  1. http协议--》超文本传输协议
  2. 用途:网站中浏览器获取网页的过程
    编写基于http协议的数据传输
    将想要获取的内容,以http协议的格式发送给服务端,服务端根据格式进行解析获取到真实需求,将结果以http协议的格式回复给客户端
  3. 特点:
    1. 应用层协议,传输层使用tcp服务
    2. 简单,灵活,可以使用多种编程语言操作
    3. 无状态的协议,即不记录用户的输入内容
    4. http1.1 ---》http2.0 技术成熟度和稳定性,http1.1 支持持久连接

http请求(Request)

  1. 请求格式:
    1. 请求行  具体的请求类别和请求内容
       
      GET       /index.html  HTTP/1.1
      请求类别    请求内容     协议版本

      请求类别:

      请求名作用
      GET获取网络资源(通过地址栏发起来的请求是get请求)
      POST提交一定的附加数据,得到返回结果
      HEAD获取响应头
      PUT更新服务器资源
      DELETE删除服务器资源
      CONNECT 
      TRACE用于测试
      OPTIONS获取服务器性能(跨域先会发一次,简称:嗅探)

       

    2. 请求头 :对请求的具体描述 
      Accept: text/html 
      每一个键值对占一行,描述了一个特定信息
       
    3. 空行
       
    4. 请求体 :具体的参数或者提交的内容
      get参数或者post提交的内容

http响应(response)

  1. 响应格式
    1. 响应行 :反馈具体的响应情况
      HTTP/1.1   200     OK 
      协议版本   响应码  附加信息
      响应码:
      响应码作用
      1xx提示信息,表示请求已经接受
      2xx响应成功
      3xx响应需要重定向
      4xx客户端错误
      5xx服务端错误
      常见响应码作用
      200成功
      404请求内容不存在
      401没有访问权限
      500服务器发生未知错误
      503服务器暂时不能执行
    2. 响应头 
      Accept-Ranges: bytes 
      以键值对方式给出响应信息的具体描述
      每个键占一行
    3. 空行
    4. 响应体 :将客户端请求内容进行返回

要求:

  • 直到http作用
  • 掌握http协议,请求和响应的格式以及每一部分做什么
  • 掌握http协议中请求的基本类型和作用
  • 直到http协议响应码的类型和表达含义
  • 了解通过http协议请求网页的流程

作业:编写一个程序,完成一个文本文件(图片)在服务端和客户端之间的传输要求使用tcp套接字

解析:

from socket import *
from time import sleep 

s = socket()

s.bind(('0.0.0.0',8888))
s.listen(5)

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

f = open('img.jpg','rb')
#将文件名称告知对方
c.send('img.jpg'.encode())
sleep(0.1)

while True:
    data = f.read(1024)
    if not data:
        break
    c.send(data)
    
sleep(0.1)
c.send('##'.encode())

data = c.recv(1024)
print(data.decode())

f.close()
c.close()
s.close()

 

from socket import * 

s = socket()

s.connect(('172.60.50.181',8888))

filename = s.recv(1024).decode()

f = open('/home/tarena/'+filename,'wb')

while True:
    data = s.recv(1024)
    if data == b'##':
        break
    f.write(data)

s.send("接收完成".encode())

f.close()
s.close()

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值