Python学习笔记30:网络编程基础

一、C/S和B/S架构

两个程序之间通讯的应用可以分为两种:

应用类:基于C/S架构开发的QQ、微信、网盘,需要安装桌面应用

web类:基于B/S架构开发的百度、知乎、博客园等可以通过浏览器直接使用的应用

C/S即:Client和Server,客户端和服务器

B/S即:Browser和Server,浏览器和服务器

优势:统一入口,不需要安装那么多APP,使用成本低

 

二、网络基础

计算机之间如何通信?

早期:联机

名词:网卡,网口

两台机器之间,插上网线就可以通信

网卡

mac地址,全球唯一的,出厂即有

mac地址

每块网卡出厂时都被烧制上一个世界唯一的mac地址,长度为48位2进制,通常由12位16进制数表示(前六位是厂商编号,后六位是流水线号)。发送端和接收端的地址便是指网卡的地址,即mac地址。后面嫌弃mac地址太麻烦,所以出现了IP地址用来定位每一个主机

IP地址和IP协议

  • 规定网络地址的协议叫ip协议,它定义的地址称之为ip地址,广泛采用的v4版本即ipv4,它规定网络地址由32位2进制表示
  • 范围0.0.0.0-255.255.255.255。为什么是255,因为计算机只认识二进制,所以IP地址的十进制最后还是要转为二进制,计算机一个字节是8位,最大11111111=255
  • 一个ip地址通常写成四段十进制数,例:172.16.10.1,也叫4个点分十进制 - ipv4协议,还有ipv6,就是0.0.0.0.0.0 - 255.255.255.255.255.255
  • IP保留地址:a类网 10.0.0.0~10.255.255.255;b类网 172.16.0.0~172.31.255.255;c类网 192.168.0.0~192.168.255.255

arp协议

地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。说到底就是通过IP地址确定mac地址

 

以太网:局域网和交换机

交换机:

电脑上的网线最终都连到交换机里面去了,多台机器通信问题

广播:主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无条件复制并转发,所有主机都可以接收到所有信息(不管你是否需要)

广域网与路由器

为了避免广播风暴,所以又出现了路由器,又叫网关,用来控制不同局域网通信。

局域网:

局域网(Local Area Network,LAN)是指在某一区域内由多台计算机互联成的计算机组。局域网是封闭型的,可以由办公室内的两台计算机组成,也可以由一个公司内的上千台计算机组成。

那么怎么确定两个不同的电脑IP是否在同一个局域网呢?

子网掩码

所谓”子网掩码”,就是表示子网络特征的一个参数。它在形式上等同于IP地址,也是一个32位二进制数字,它的网络部分全部为1,主机部分全部为0。比如,IP地址172.16.10.1,如果已知网络部分是前24位,主机部分是后8位,那么子网络掩码就是11111111.11111111.11111111.00000000,写成十进制就是255.255.255.0。

知道”子网掩码”,我们就能判断,任意两个IP地址是否处在同一个子网络。方法是将两个IP地址与子网掩码分别进行AND运算(两个数位都为1,运算结果为1,否则为0),然后比较结果是否相同,如果是的话,就表明它们在同一个子网络中,否则就不是。

比如,已知IP地址172.16.10.1和172.16.10.2的子网掩码都是255.255.255.0,请问它们是否在同一个子网络?两者与子网掩码分别进行AND运算,

172.16.10.1:10101100.00010000.00001010.000000001
255255.255.255.0:11111111.11111111.11111111.00000000
AND运算得网络地址结果:10101100.00010000.00001010.000000001->172.16.10.0

 

172.16.10.2:10101100.00010000.00001010.00000010
255255.255.255.0:11111111.11111111.11111111.00000000
AND运算得网络地址结果:10101100.00010000.00001010.000000001->172.16.10.0
结果都是172.16.10.0,因此它们在同一个子网络。

tcp协议和udp协议

用于应用程序之间的通信。如果说ip地址和mac地址帮我们确定唯一的一台机器,那么我们怎么找到一台机器上的一个软件呢?

端口

我们知道,一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。

  • 端口范围:0-65535 
  • 8000-酷狗音乐  22-ssh  3306-mysql
  • ip:确定唯一的一台机器
  • 端口:确定为一个一个程序
  • ip地址+端口号 : 在全网找到唯一的一台机器+唯一的应用
  • 我们选择端口 : 8000之后,前面的一般是系统会用的到
  • 同一时间只会有一个程序占用一个端口

TCP协议

当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止。

重点:看图理解三次握手和四次挥手

UDP协议

当应用程序希望通过UDP与一个应用程序通信时,传输数据之前源端和终端不建立连接。当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。

TCP协议和UDP协议对比
TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 
UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快

  

当需要和不同国家,不同地区通信时,就需要互联网协议了。

互联网协议与osi模型

每层运行常见物理设备

每层运行常见的协议

 

socket概念(又叫套接字)

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

 

所以转换到TCP协议和UDP协议关系见下图

 

套接字的使用(python模拟客户端和服务器进行通信)

基于TCP协议的socket

tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

server端

import socket
from socket import SOL_SOCKET,SO_REUSEADDR

sk = socket.socket()  # 理解成买手机
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) # 加在bind前,可以解决address already in use问题
sk.bind(('127.0.0.1',8889)) # 里面是元组,绑定手机卡,127.0.0.1默认是本机的ip,8000以后的端口号都可以
sk.listen()    # 监听,等着别人给打电话

conn,addr = sk.accept() # 接收到别人的电话,connection电话线,address对方电话号码
ret = conn.recv(1024)   # 听别人说话,一般默认为1024的倍数,指的的是接收的长度
print(ret)
conn.send(b'hi')  # 和别人说话,一般为bytes类型

ret = conn.recv(1024)
print(ret.decode('utf-8'))
conn.send(bytes('牛肉拉面',encoding='utf-8'))

conn.close()      # 挂电话
sk.close()        # 关机

Client端

import socket

sk = socket.socket()  # 买手机
sk.connect(('127.0.0.1',8889)) # 拨号打电话

sk.send(b'hello') # 说话
ret = sk.recv(1024)
print(ret)

sk.send(bytes('中午吃什么?',encoding='utf-8'))
ret = sk.recv(1024)
print(ret.decode('utf-8'))

sk.close()

  

实现更友好的交流版本

server端

import socket
from socket import SOL_SOCKET,SO_REUSEADDR

sk = socket.socket()  # 买手机
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) # 加在bind前,可以解决address already in use问题
sk.bind(('127.0.0.1',8887)) # 里面是元组,绑定手机卡,127.0.0.1默认是本机的ip,8000以后的端口号都可以
sk.listen()    # 监听,等着别人给打电话
conn,addr = sk.accept() # 接收到别人的电话,connection电话线,address对方电话号码

while 1:
    ret = conn.recv(1024).decode('utf-8')
    if ret == 'bye':
        break
    print(ret)
    info = input('>>>')
    conn.send(bytes(info,encoding='utf-8'))
    # ret = conn.recv(1024)   # 听别人说话,一般默认为1024的倍数,指的的是接收的长度
    # print(ret)
    # conn.send(b'hi')  # 和别人说话,一般为bytes类型
    #
    # ret = conn.recv(1024)
    # print(ret.decode('utf-8'))
    # conn.send(bytes('牛肉拉面',encoding='utf-8'))

conn.close()      # 挂电话
sk.close()        # 关机

Client端

import socket

sk = socket.socket()  # 买手机
sk.connect(('127.0.0.1',8887)) # 拨号打电话

while 1:
    info = input('>>>')
    sk.send(bytes(info,encoding='utf-8'))
    ret = sk.recv(1024).decode('utf-8')
    print(ret)
    if ret == 'bye':
        sk.send(bytes('bye'))
        break
    # sk.send(b'hello') # 说话
    # ret = sk.recv(1024)
    # print(ret)
    #
    # sk.send(bytes('中午吃什么?',encoding='utf-8'))
    # ret = sk.recv(1024)
    # print(ret.decode('utf-8'))

sk.close()

 

 

更多精彩内容,参见:https://www.cnblogs.com/Eva-J/articles/8244551.html 

posted @ 2019-07-12 21:12  zheng1076  阅读(298)  评论(0编辑  收藏  举报