Title

网络编程简介

网络编程:

1.软件开发架构

  • C/S架构:(应用类)

    ​ Client: 客户端

    ​ Server: 服务端

    ​ 比如: 微信客户端、QQ客户端等...

    • 优点:软件使用稳点,节省网络资源
    • 缺点:安装麻烦,需要占用手机或计算机内存资源,每次跟新都需要下载更新版本

  • B/S架构:(web类)

    ​ Browser(本质上也是一个客户端): 浏览器 S

    ​ erver: 服务端

    ​ 比如: 在浏览器上输入一个 网址 就可以访问服务器

    • 优点:软件的使用方便,不需要下载和更新
    • 缺点:极度依赖网络环境

客户端与服务端都需要唯一的地址,但是客户端不需要固定地址,而服务端需要固定地址,并且保证一直稳定运行提供服务,并且支持并发

# 世界五大浏览器
'''
一.IE浏览器: 
IE是微软公司旗下浏览器,是目国内用户量最多的浏览器。


二.Opera浏览器(欧朋浏览器): 
Opera是挪威Opera Software ASA公司旗下的浏览器,使用自己研发的Presto内核。2016年奇虎360和昆仑万维收购了Oprea浏览器,改用当时Google开源的webkit内核

三.Safari浏览器
2003年,苹果公司在苹果手机上开发Safari浏览器,利用自己得天独厚的手机市场份额使Safari浏览器迅速成为世界主流浏览器。

四.Firefox浏览器:
采用Gecko作为内核。Gecko是一个开源的项目,代码完全公开,因此受到很多人的青睐。

五.Chrome浏览器: 
Chrome浏览器是google旗下的浏览器,最开始Chrome采用webkit作为浏览器内核,直到2013年,google宣布不再使用苹果的webkit内核,开始使用webkit的分支内核Blink。

'''



# 四大浏览器内核
'''
四大内核分别是:
Trident(也称IE内核,IE浏览器内核)、
webkit(Safari浏览器内核)、
Blink(Chrome浏览器内核,Opera浏览器内核)、
Gecko(Firefox浏览器内核)。
'''


不同的浏览器由于内核不同会在前端开发时遇到兼容问题

2.互联网协议

  • 如何实现计算机与计算机之间进行无障碍通信
    • 物理链接介质(电话线,网线,网卡等)
    • 互联网协议(一套所有计算机都遵循的标准)

补充:

以太网: 以太网是目前应用最普遍的局域网技术

​ 第一类是经典以太网,第二类是交换式以太网,使用了一种称为交换机的设备连接不同的计算机

交换机:所有链接了同一个交换机的电脑彼此都是互联的

了解:

三层交换机:即具有交换机又具有路由器功能

四层交换机:能够根据你走的什么协议找到对应的应用

互联网协议按照功能不同可以分为osi (开放系统互联(Open System Interconnection)) 七层或tcp/ip五层或tcp/ip四层

物理层:

物理链接介质,接收和传递电信号(高低电平),即一堆二进制字符0111010101010

物理层无法获取具体数据内容以及分解字符串,故将电信号传给数据链路层

数据链路层(遵循ARP协议)

地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。

拿到物理层电信号后:

​ 我要知道数据是什么?

​ 我要知道数据是给谁的?

“以太网协议”:

将一组电信号称为一组数据报或者数据帧

1)规定一套分组的方式:

​ 获取电信号真实数据。

​ 电信号是一个数据报。

​ 报头(head): 18个字节,发送者(源地址), 6个: 接收者(目标地址),6个: 数据类型6个

​ 数据(data):电信号具体的数据(最短45个字节,最长1500字节)

  1. 规定每一台电脑必须要有一个网卡(电脑插入网线的地方):
  • 每一块网卡都会有一串世界上独一无二的数字: - 12位16进制的数字,称之为 "mac地址" : - 前6位: 产商号 - 后6位: 流水号
  • mac地址作用(*******): 标识全世界上一台独一无二的计算机。

3)工作的方式:

​单播:

广播:

缺点:

广播风暴:只能在局域网内实现通信, 无法跨局域实现通信

网络层

规定计算机都必须有一个ip地址,ip协议可以跨局域网传输

  • ip地址(ip协议):点分十进制的数字组成 180.101.49.11

    最小范围: 0.0.0.0 -

    最大范围: 255.255.255.255

  • ip的版本:

    • IPV4:
    • IPV6:

    ip的作用:

    用于表示全世界某一台计算机的位置在局域网的位置。

    总结: ip地址 + mac地址: 标识全世界某一个局域网内的,某一台计算机。

传输层:

tcp与udp都是基于 “端口” 实现通信的。

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

主要是软件与软件之间进行通信。

  • port端口: 0~65535用来标识一台计算机之上基于网络通信的应用软件,0~1024操作系统自己用的,一般情况下8000之后的端口我们可以任意使用,8000之前的通常会有相应的程序默认使用 用于标识计算机中某一个独一无二软件。

三次握手和四次挥手

三次握手

建立双向通道的过程称之为三次握手,建立通道的发起者可以是客户端也可以是服务端,下面我们就以客户端先主动发起为例

  • 客户端会朝服务端发送一个请求询问服务端:"我能不能挖一条通往你家的地道"

  • 服务端收到请求,回复说:"好吧 你挖吧",由于TCP是双向通道,客户端挖向服务端的通道只能给客户端朝服务端发消息使用,服务端要向给客户端发消息是没办法走这一条通道的,需要自己挖一条通往客户端的通道

    所以服务端在回复同意客户端挖通道的同时还会问一句:"那我能不能也挖一条通往你家的通道"

  • 客户端收到服务端请求后客户端到服务端的通道就挖成功了,然后也会同意服务端的请求,服务端挖向客户端的通道也会成功

总结:之所以称之为三次握手就是因为中间的服务端的同意,和请求合并成了一次请求

四次挥手

建立一个连接需要三次握手,而终止一个连接要经过四次握手

当服务端或者客户端不想再与对方进行通信之后,双方任意一方都可以主动发起断开链接的请求,我们还是以客户端主动发起为例

  • 客户端由于已经没有任何需要发送给服务端的消息了,所以发起断开客户端到服务端的通道请求

  • 服务端收到该请求后同意了 至此客户端到服务端的单项通道断开

  • 服务端这个时候不会立刻朝客户端发器请求说那我也断开到你家的通道吧,服务端需要想想我手上还有没有需要发送给客户端的消息,如果还有的话,那我不能立马断开,先把数据发完才能断

    等服务端检查完毕之后发送也没有数据要给客户端了,这个时候就会朝客户端发起断开服务端到客户端的通道请求

  • 客户端同意该请求,至此四次挥手完成

总结:挥手必须是四次,中间的两次不能合并成一次,原因就在于需要检查是否还有数据需要给对方发送

  • 反馈机制: 客户端往服务端发送请求,服务端必须返回响应,告诉客户端收到请求了,并且将服务端的数据一并返回给客户端。

    C-->S: 一次请求,必须有一次响应。

    缺点:

    洪水攻击: 指的是通过伪造大量的请求,往对方服务器发送请求,导致对方服务器响应跟不上,以至于瘫痪。linux系统有个参数可以限制。

    半连接池listen: 限制用户在同一个时间段内的访问数量。

总结: mac地址 + ip地址 + port端口: 标识的是全世界范围内某一个局域网内某一台计算机上的某一个软件。

应用层:

  • http协议
  • ftp协议

3.socket套接字通信

  • 什么是socket?

    socket是一个模块, 又称套接字,用来封装 互联网协议(应用层以下的层)。

  • 为什么要有socket?

    socket可以实现 互联网协议应用层以下的层的工作。提高开发效率

  • 怎么使用socket?

    import socket

    写socket套接字:

    Client (客户端)/Server(服务端)

'''
客户端
'''
import socket

# 获取套接字
client = socket.socket()

# 尝试与服务端建立链接
client.connect(
   ('127.0.0.1', 8472)
)

while True:
   # 输入向服务端发送的信息
   send_data = input('客户端>>>: ')

   # 将信息编码
   client.send(send_data.encode('utf-8'))
   # 接收服务端端的数据,1024表示接收数据长度,可修改
   data = client.recv(1024)
   # 判断是否服务端申请关闭通道
   if data.decode('utf-8') == 'q':
       break
   if len(data) == 0:
       break
   # 打印数据信息
   print(data.decode('utf-8'))

# 关闭通道
client.close()
'''
服务端优先启动
'''
import socket

# 获取套接字(类似于买了一个手机)
server = socket.socket()

# 绑定ip和端口地址(类似于手机绑定手机卡)
server.bind(
    ('127.0.0.1', 8472)
)


# 半连接池(监听链接)
server.listen(3)

while True:
    # 接收客户端链接信息
    conn, addr = server.accept()

    while True:

        try:  # 监听代码块是否有异常出现
            # 获取客服端数据
            data = conn.recv(1024) # 设置接收数据长度

            # 判断是否接收数据0
            if len(data) == 0:
                break
            # 判断客户端是否申请断绝联系
            if data.decode('utf-8') == 'q':
                break
            print(data.decode('utf-8'))

            # 向客服端发送信息
            send_data = input('服务端>>>: ')
            conn.send(send_data.encode('utf-8'))

        # 将异常收集返回出来
        except Exception as e:
            print(e)
            break

    # 关闭通道
    conn.close()

粘包问题

    1. 问题: 无法确认对方发送过来数据的大小。
    1. 问题: 在发送数据间隔短并且数据量小的情况下,会将所有数据一次性发送。

解决: 确认对方数据的大小。

解决粘包问题(struct模块)

无论哪一端先发送数据

客户端 :

1.先制作报头,并发送 (struct)

2.发送真实数据

服务端:

1接收报头,并解包获取真实数据长度

2.根据真实数据长度 接收真实数据 ,recv(真实数据长度)

1.struct模块
是一个python内置的模块, 它可以将固定长度的数据,打包成固定格式的长度。
模式i: 4
2.作用:
可以将真实数据,做成一个固定长度多的报头,客户端发送给服务端,服务端可以接收报头,
然后对报头进行解包,获取真实数据的长度,进行接收即可

import struct

data =b'snjab'

print(data)

print(len(data))

# 打包制作报头

header = struct.pack('i', len(data))

print(header)

res = struct.unpack('i', header)[0]
print(res)


#客户端

import socket
import json
import struct

client = socket.socket()

client.connect(
    ('127.0.0.1', 8978)
)

while True:
    movie_name = input('请上传电影名称: ')
    # 伪装一个电影长度
    movie_len = 10000

    send_dic = {'movie_name': movie_name,
                "movie_len": movie_len}
    # 改成json模式
    json = json.dumps(send_dic)
    # print(json)
    # print(json.encode('utf-8'))
    # print(len(json.encode('utf-8')))
    json_bytes = json.encode('utf-8')

    header = struct.pack('i', json_bytes)
    client.send(header)
    client.send(json_bytes)

# 服务端
import socket
import struct
import json

server = socket.socket()

server.bind(
    ('127.0.0.1', 8978)
)

server.listen(2)

while True:
    conn, addr = server.accept()
    while True:
        try:
            header = conn.recv(4)  # 获取报头

            # 解开报头
            json_len = struct.unpack('i', header)[0]

            # 接收真正长度

            json_bytes_date = conn.recv(json_len)

            json_data = json_bytes_date.decode('utf-8')

            back_dic = json.loads(json_data)
            print(back_dic)
        except Exception as e:
            print(e)


    conn.close()

.UDP协议 (了解)

称之为数据包协议,不可靠协议

特点:

  • 不需要建立链接。
  • 不需要知道对方是否收到。
  • 数据不安全
  • 传输速度快
  • 能支持并发
  • 不会粘包
  • 无需先启动服务端再启动客户端

优点:

  • 传输速度快
  • 能支持并发
  • 不会粘包

缺点:

  • 数据不安全, 容易丢失

应用场景: 早期的QQ聊天室。

2.TCP协议(称为流式协议):

优点:

  • 数据安全 缺点:
  • 传输速度慢
  • 粘包

面试: TCP与UDP的区别, 简述优缺点即可。(*******)

'''
server,不需要优先启动服务端
'''

import socket

# socket.SOCK_DGRAM ------>UPD协议
server = socket.socket(type=socket.SOCK_DGRAM)

# 服务端需要绑定一个地址,让别人知道服务端在哪
server.bind(
    ('127.0.0.1', 8594)
)

while True:

    # 接收数据给服务端的用户地址
    date, addr = server.recvfrom(1024)

    print(addr)
    print(date.decode('utf-8'))





    # 无论服务端还是客户端,发送消息时,都必须知道对方是谁
    # server.sendto(msg, addr)
'''
客户端
'''
import socket

client = socket.socket(type=socket.SOCK_DGRAM)

address = ('127.0.0.1', 8594)
print(address)

while True:
    msg = input('客户端输入信息: ').encode('utf-8')
    client.sendto(msg, address)

posted @ 2019-12-05 23:02  Mr江  阅读(263)  评论(0编辑  收藏  举报