Python网络编程(OSI模型、网络协议、TCP)

本文深入浅出地介绍了网络的基本概念,包括网络的定义、结构、目的及网络协议,重点阐述了OSI模型与TCP/IP模型的区别,并详细解析了Python中的套接字编程,演示了服务端与客户端的通信过程。

前言:

什么是网络?

网络是由节点和连线构成,表示诸多对象及其相互联系。

在数学上,网络是一种图,一般认为专指加权图。

网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类 型的实际问题中抽象出来的模型

在计算机领域中,网络是信息传输、接收、共享的虚拟平台,通过它把各个点、面、体的信息联系到一起,从而实现这些资源的共享

网络是人类发展史来最重要的发明,提高了科技和人类社会的发展。

在1999年之前,人们一般认为网络的结构都是随机的。但随着Barabasi和Watts在1999年分别发现了网络的无标度和小世界特性并分别在世界著名的《科学》和《自然》           杂志上 发表了他们的发现之后,人们才认识到网络的复杂性。

网络会借助文字阅读、图片查看、影音播放、下载传输、游戏、聊天等软件工具从文字、图片、声音、视频等方面给人们带来极其丰富的生活和美好的享受。

 

 

 

 

网络目的:

      网络传输的目的是什么?

  •          没错就是:数据传输

 

  由于网络的复杂性以及各种应用硬件等等不匹配原因 

  和编码是一个道理你有你的我有我的会导致冲突等问题

  所以出现了 :ISO(国际标准化组织)

  ISO是干嘛的呢?

  •      他是一个非盈利性国际组织 这个组织制定了一个用于计算机或通讯系统间的互联网标准体系
  •      叫OSI模型  不仅包括一系列抽象的术语或概念,也包括具体的协议
  •      OSI公有七层 :

 

  1.     应用层: 提供用户服务,具体的内容由特定的程序规定
  2.     表示层: 提供数据的加密和压缩优化
  3.     会话层: 确定建立应用链接,选择传输服务
  4.     传输层: 提供数据传输服务,进行流量控制
  5.     网络层: 路由选着,网络互联
  6.     链路层: 提供链路交换,具体消息的发送
  7.     物理层: 物理硬件,接口,网卡的规定

 

四层模型:

  1.     应用层 :  应用层   表示层  会话层
  2.     传输层 :  传输层
  3.     网络层 :  网络层
  4.     物理链路层: 链路层和物理层

 

五层模型(tcp/ip模型):

  1.     应用层 : 应用层   表示层  会话层
  2.     传输层 : 传输层
  3.     网络层 : 网络层
  4.     链路层 : 链路层
  5.     物理层 : 物理层

 

 

OSI模型优点

  •              将功能分开 降低网络中的耦合度,
  •              使用开发流程更加清晰,每部分各司其职

 

高内聚低耦合:

  1.   高内聚:每个模块功能尽量单一,不会多个功能掺杂
  2.   低耦合:尽量降低每个模块之间的关联性

 

 

 

 

网络协议:

  •           在网络通讯中协议必须遵守的规定,
  •           如建立什么连接,消息结构如何解析等
  • 应用层:TFTP(文件传输)、HTTP(超文本传输协议)、DNS(域名解析)、SMTP(邮件传输)
  • 传输层:TCP、UDP
  • 网络层:IP
  • 物理层:IEEE

 

iPython3:socket模块

 

网络相关概念:

    网络主机:在网络上确定一台主机

  1.         本地使用:127.0.0.1 或 “localhost”
  2.         网络地址:“0.0.0.0” 或 “172.168.40.53”
  •     ifconfig:查看本机IP (ens33:本地IP  lo:本地回还)
  •     ipconfig:windoes中
  •     socket.gethostname() :                      获取本机主机名
  •     socket.gethostbyname('tedu') :        利用主机名获取ip
  •     socket.gethostbyname('localhost'):   获取本地ip

 

常用IP地址:

  1. IPv4: 点分十进制   例如:192.168.1.3   取值0~255(32位)
  2. IPv6: 128位

 

网络连接测试

    ping 172.18.32.47

 

特殊ip

  1.     127.0.0.1            本地IP测试
  2.     0.0.0.0                自动使用本地可用网卡IP
  3.     192.168.1.0        代表网段
  4.     192.168.1.1        通常为网关地址
  5.     192.168.1.255    广播地址

 

 

访问主机IP地址:

    socket.gethostbyaddr('127.0.0.1')

    ('localhost', [], ['127.0.0.1'])

         主机     别名      ip地址

 

IP十六进制转换:

  •     socket.inet_aton('192.168.1.2')
  •     b'\xc0\xa8\x01\x02'
  •     socket.inet_ntoa(b'\xc0\xa8\x01\02')
  •      '192.168.1.2'

 

域名:

  •     是指网络服务器地址在网络上的名称

端口号:

  • 端口号是地址的一部分,在一个系统中每个网络(区分应用ip
  • 应用监听不同的端口,以获取对应的端口传递信息
  • 取值范围:1---------65535
  •                  1---------255   一些通用端口(众所周知的程序占用)
  •                  256------1023  系统端口
  •                 1024-----65535 自用端口

 

获取应用程序的端口:

  1.     socket.getservbyname('ssh')
  2.     22
  1.     socket.getservbyname('mysql')
  2.     3306

 

 

传输层服务:

 

 面向连接的传输服务(tcp协议):

  •         传输特征:
  •                可靠的数据传输:
  •                       可靠性:无失序、无差错、无重复、无丢失
  •                       在数据传输前和传输后需要建立连接和断开链接
  •        面向传输服务建立连接的过程:‘三次握手
  1. 客户端向服务器发送链接请求
  2. 服务器接受到请求进行确认,返回确认报文
  3. 客户端收到服务器回复最终确认链接
  •           面向传输服务断开链接的过程:‘四次挥手’
    1. 主动方发送报文,告知被动方要断开链接
    2. 被动方回复报文,表示已经接受到请求,准备断开
    3. 被动方再次发送报文,表示准备处理就绪,可以断开
    4. 主动方发送确认报文,断开链接
  •         应用情况:
  •     适用于传输较大的内容或文件,网络良好,
  •     需要保证传输可靠性的情况
  •     e.g.  信息聊天,文件上传下载,邮件,网页获取

 面向无连接的传输服务(udp协议):

  1. 不保证传输的可靠性
  2. 没有建立连接和断开的过程
  3. 数据的收发比较自由
  • 适用情况: 
  •     网络情况较差,对可靠性要求不高,收发消息的两端
  •     e.g.:网络视频,群聊,广播等

 

 

 

 

socket 套接字编程:

    目的:

  • 通过编程语言提供的套接字编程接口
  •           可以更简单的完成基于tcp/udp的编程

    套接字:

  • 是完成上述目标的一种编程手段

    套接字类别:

      1.流式套接字(SOCK_STREAM):

  •          传输层基于套接字的协议通信
  •          面向连接可靠的传输  tcp的传输   流式套接字

      2.数据报套接字(SOCK_DGRAM):

  •          面向无连接不可靠的传输 udp的传输  数据报套接字

      3.低层套接字(SOCK_RAM):

  • 访问底层协议套接字

 

TCP服务端:

   import socket

   1.创建套接字(函数):

      socket.socket(sock_family = AF_INET,

              sock_type = SOCK_STREAM,

      proto = 0)

      功能:

  • 创建套接字

      参数:

  •  sock_family地址族类型   AF_INET:IPV4网络通讯
  •  sock_tpye:套接字类型   SICK_STREAM :流式   SOCK_DGRAM:数据报
  •  proto:通常为0  选定子协议类型
  •  返回值:返回一个套接字对象

   2.绑定地址(函数):

      sockfd.bind(addr)

        功能:

  • 绑定地址

        参数:

  • addr--->元组  (ip, port) ("0.0.0.0", 8888)

   3.设置监听套接字:

      sockfd.listen(n)

        功能:

  • 将套接字设置为监听套接字,创建监听队列

参数:

  • 监听队列大小
  • 一个监听套接字可以连接多个客户端

   4.等待接受客户端链接:

      connfd,addr = sockfd.accept()  阻塞状态

      功能:

  • 阻塞等待并处理客户端链接

      返回值:

  1.            connfd:新的套接字,用于和客户端通讯
  2.            addr:链接客户端的地址(ip, port)

      阻塞函数

  •     当程序运行到阻塞函数位置,如果某种条件
  •     没有达成则暂停程序运行,直到条件达成结束阻塞

-

   5.消息的收发:

      data = connfd.recvbuffersize

        功能:

  • 接受消息

        参数:

  •        一次接受消息的大小 字节
  •         返回值:返回接受的内容

      n = connfd.send(data)

        功能:

  • 发送消息

        参数:

  • 要发送的内容(bytes格式)
  •         返回值:返回实际发送的字节数

   6.关闭套接字

      sockfd.close()

 

客户端:

    1.创建套接字 (和服务端套接字类型相同)

    2.发起链接

       connect(addr)

          功能:

  • 向服务端发起链接

  参数:

  • 服务器地址  (元组

    3.消息收发

    4.关闭套接字

 

示例

服务端:

 

 

<span style="color:#f8f8f2"><code class="language-python"><span style="color:#66d9ef">from</span> socket <span style="color:#66d9ef">import</span> <span style="color:#f8f8f2">*</span>

<span style="color:slategray"># 创建套接字对象</span>
sockd <span style="color:#f8f8f2">=</span> socket<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 绑定IP地址</span>
sockd<span style="color:#f8f8f2">.</span>bind<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"127.0.0.1"</span><span style="color:#f8f8f2">,</span> <span style="color:#ae81ff">6666</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 设置监听套接字</span>
sockd<span style="color:#f8f8f2">.</span>listen<span style="color:#f8f8f2">(</span><span style="color:#ae81ff">5</span><span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 等待客户端链接</span>
cond<span style="color:#f8f8f2">,</span> addr <span style="color:#f8f8f2">=</span> sockd<span style="color:#f8f8f2">.</span>accept<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 接受客户端消息(单次1024字节)</span>
data <span style="color:#f8f8f2">=</span> cond<span style="color:#f8f8f2">.</span>recv<span style="color:#f8f8f2">(</span><span style="color:#ae81ff">1024</span><span style="color:#f8f8f2">)</span>
<span style="color:#66d9ef">print</span><span style="color:#f8f8f2">(</span>data<span style="color:#f8f8f2">.</span>decode<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 发送消息</span>
cond<span style="color:#f8f8f2">.</span>send<span style="color:#f8f8f2">(</span>b<span style="color:#a6e22e">"Hello, I'm the server"</span><span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 关闭套接字</span>
cond<span style="color:#f8f8f2">.</span>close<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span>
sockd<span style="color:#f8f8f2">.</span>close<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span>
</code></span>

 

这里本机测试可以利用两个进行 telnet命令链接服务端测试

 

 

服务器:

<span style="color:#f8f8f2"><code class="language-python">

<span style="color:#66d9ef">from</span> socket <span style="color:#66d9ef">import</span> <span style="color:#f8f8f2">*</span>

<span style="color:slategray"># 创建套接字</span>
sockfd <span style="color:#f8f8f2">=</span> socket<span style="color:#f8f8f2">(</span>AF_INET<span style="color:#f8f8f2">,</span> SOCK_STREAM<span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 绑定地址</span>
sockfd<span style="color:#f8f8f2">.</span>bind<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"0.0.0.0"</span><span style="color:#f8f8f2">,</span> <span style="color:#ae81ff">8888</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 设置监听</span>
sockfd<span style="color:#f8f8f2">.</span>listen<span style="color:#f8f8f2">(</span><span style="color:#ae81ff">5</span><span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 等待客户端链接</span>
<span style="color:#66d9ef">print</span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"waiting for connect...."</span><span style="color:#f8f8f2">)</span>
conn<span style="color:#f8f8f2">,</span> addr <span style="color:#f8f8f2">=</span> sockfd<span style="color:#f8f8f2">.</span>accept<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span>
<span style="color:#66d9ef">print</span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"Connect from"</span><span style="color:#f8f8f2">,</span> addr<span style="color:#f8f8f2">)</span>
<span style="color:#66d9ef">print</span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"Connect from"</span><span style="color:#f8f8f2">,</span> conn<span style="color:#f8f8f2">)</span>

<span style="color:slategray"># 消息收发</span>
<span style="color:#66d9ef">while</span> <span style="color:#ae81ff">True</span><span style="color:#f8f8f2">:</span>
    data <span style="color:#f8f8f2">=</span> conn<span style="color:#f8f8f2">.</span>recv<span style="color:#f8f8f2">(</span><span style="color:#ae81ff">1024</span><span style="color:#f8f8f2">)</span>
    <span style="color:#66d9ef">if</span> data<span style="color:#f8f8f2">.</span>decode<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span> <span style="color:#f8f8f2">==</span> <span style="color:#a6e22e">""</span><span style="color:#f8f8f2">:</span>
        n <span style="color:#f8f8f2">=</span> conn<span style="color:#f8f8f2">.</span>send<span style="color:#f8f8f2">(</span>b<span style="color:#a6e22e">"Bey"</span><span style="color:#f8f8f2">)</span>
        <span style="color:#66d9ef">break</span>
    <span style="color:#66d9ef">print</span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"Receive"</span><span style="color:#f8f8f2">,</span> data<span style="color:#f8f8f2">.</span>decode<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span>
    n <span style="color:#f8f8f2">=</span> conn<span style="color:#f8f8f2">.</span>send<span style="color:#f8f8f2">(</span>b<span style="color:#a6e22e">"Receive your message"</span><span style="color:#f8f8f2">)</span>
    <span style="color:#66d9ef">print</span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"send %d"</span> <span style="color:#f8f8f2">%</span> n<span style="color:#f8f8f2">)</span>
<span style="color:slategray"># 关闭套接字</span>
conn<span style="color:#f8f8f2">.</span>close<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span>
sockfd<span style="color:#f8f8f2">.</span>close<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span>
</code></span>


客户端:

 

<span style="color:#f8f8f2"><code class="language-python"><span style="color:slategray"># tcp_client.py</span>

<span style="color:#66d9ef">from</span> socket <span style="color:#66d9ef">import</span> <span style="color:#f8f8f2">*</span>

sockfd <span style="color:#f8f8f2">=</span> socket<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span>
sockfd<span style="color:#f8f8f2">.</span>connect<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"172.18.32.31"</span><span style="color:#f8f8f2">,</span> <span style="color:#ae81ff">8888</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span>
<span style="color:#66d9ef">while</span> <span style="color:#ae81ff">True</span><span style="color:#f8f8f2">:</span>
    msg <span style="color:#f8f8f2">=</span> input<span style="color:#f8f8f2">(</span><span style="color:#a6e22e">"Msg>>"</span><span style="color:#f8f8f2">)</span>
    <span style="color:#66d9ef">if</span> msg <span style="color:#f8f8f2">==</span> <span style="color:#a6e22e">""</span><span style="color:#f8f8f2">:</span>
        <span style="color:#66d9ef">break</span>
    sockfd<span style="color:#f8f8f2">.</span>send<span style="color:#f8f8f2">(</span>msg<span style="color:#f8f8f2">.</span>encode<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span>
    data <span style="color:#f8f8f2">=</span> sockfd<span style="color:#f8f8f2">.</span>recv<span style="color:#f8f8f2">(</span><span style="color:#ae81ff">1024</span><span style="color:#f8f8f2">)</span>
    <span style="color:slategray"># if msg == "Bye":</span>
    <span style="color:slategray">#     break</span>
    <span style="color:#66d9ef">print</span><span style="color:#f8f8f2">(</span>data<span style="color:#f8f8f2">.</span>decode<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span><span style="color:#f8f8f2">)</span>
sockfd<span style="color:#f8f8f2">.</span>close<span style="color:#f8f8f2">(</span><span style="color:#f8f8f2">)</span></code></span>

 

简单的消息传输:

>>>>阅读全文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值