码迷,mamicode.com
首页 > 其他好文 > 详细

网络编程

时间:2020-07-03 12:23:04      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:说话   控制   占用   可靠传输   理解   ftp服务   客户端程序   元组   通话   

网络编程就是 1.udp 2.tcp

网络udp

UDP可以理解为"写信"

ip地址(重点)

什么是ip地址

ip地址: 用来在网络总唯一标识一台机器(个人PC,服务器,路由器,交换机....)

查看本机ip地址
技术图片

ip地址的分类
技术图片

端口(重点)

什么是端口

1.ip地址就类似于一栋楼的地址,而端口号就类似于门牌号
    ip地址找到目标主机,端口号找到目标进程
2. linux系统总,端口可以有 2**16(65535)个之多
    端口通过端口号来标记,端口号只有整数,范围 [0,65535]

端口是怎样分配的

端口号不是随意使用的,而是按照一定的规定进行分配
端口的分类标准有好几种,这里介绍(1) 知名端口 (2) 动态端口

知名端口

1. 知名端口就是众所周知的端口,范围 [0,1023]
2. (1)如80端口分配给给HTTP服务 (2) 21端口分配给FTP服务
    可以理解为一些常用的电话(大家都是知道的),比如火警119,救护车120之类的,不会有人专门使用电话号码和这些号码重名
3. 一般情况瞎,如果一个程序要使用知名端口需要有root权限

动态端口

大于2024的端口都是可以随意用的,但是知名端口是不能用的

1. 动态端口范围是从[1024,65535]
2. 之所以
之为动态端口,是因为它一般不固定分配某种服务,而是动态分配
3. 动态分配是指一个系统程序或引用程序需要网络通信时,它想主机申请一个端口,主机从可用的端口号中分配一个供它使用. 当这个程序关闭时,同时也就释放了所占用的端口.

怎样查看端口


socket简介

最原始的网络编程 => socket
Python使用socket和使用file其实差不多

什么是socket

socket是一种实现在不同主机之间进程通信的一种方式

1. socket(简称套接字)是进程间通信的一种方式,它与其他进程间通信的一个主要不同是: 它能是实现不同主机间的进程间通信
    (1) 我们网络上各种各样的服务大多都是基于socket来完成通信的,例如浏览网页,QQ聊天

创建socket

在Python中,使用socket模块的函数socket就可以完成创建一个socket

import socket
socket.socket(AddressFamily, Type)

1. 函数socket.socket创建一个 socket,该函数有两个参数:
(1) Address Family: 可以选择AF_INET(用户Internet进程间通信)或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET(ipv4),AF_INET(ipv6)
(2) Type: 套接字类型,可以是SOCK_STREAM(流式套接字,主要用于TCP协议)或者SOCK_DGRAM(数据报套接字,主要用于UDP协议)

2. 套接字使用流程和文件的使用流程很类似
    (a) 创建套接字
    (b) 使用套接字收发数据
    (c) 关闭套接字

# 创建一个 tcp socket
import socket

s = socket.socket(socket.AF_INET,sock.SOCK_STREAM)

# 使用套接字功能

s.close()

# 创建一个 udp socket
import socket

s = socket.socket(socket.AF_INET,sock.SOCK_DGRAM)

# 使用套接字功能

s.close()

udp网络程序收发数据

socket_udp收发数据实验
技术图片

# code02_socket循环发送数据.py
import socket


def main():

    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    while True:
        data = input("请输入要发送的数据(exit|quit): ").strip()
        if data in ("exit", "quit"):
            break
        udp_socket.sendto(data.encode("gbk"), ("192.168.50.210", 8080))

    udp_socket.close()


if __name__ == "__main__":
    main()

# code03_绑定端口接收数据.py
import socket


def main():
    # 1. 创建套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 2. 绑定一个本地端口  => socket.bind()
    # 如果一个网络程序不绑定,则系统会随机分配
    local_addr = (‘‘, 7788)  # ip端口号和地址,ip一般不用写,标识本机的任何一个ip
    udp_socket.bind(local_addr)
    while True:
        # 3. 接收数据并打印输出
        # 使用socket发送的输一个元组,接收的也是一个元组
        # (b"",("ip地址",端口号))
        recv_data = udp_socket.recvfrom(1024)  # 1024表示本次接收的最大字节数
        print(recv_data[0].decode("gbk"))
    # 4. 关闭套接字
    udp_socket.close()


if __name__ == "__main__":
    main()

Python3编码转换

str => bytes : encode 编码过程
bytes => str: decode 解码过程

# 首先str.encode()就是把 字符串转换为字节  (在Python中有  b-str)
>>> "这是一个文本字符串".encode()
b‘\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe6\x96\x87\xe6\x9c\xac\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2‘
# str.encode()还可以接收参数
>>> "这是一个文本字符串".encode("utf-8")
b‘\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe6\x96\x87\xe6\x9c\xac\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2‘
# 对应 str -> bytes -> str 
>>> "这是一个文本字符串".encode("utf-8").decode("utf-8")
‘这是一个文本字符串‘
>>> b‘\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe6\x96\x87\xe6\x9c\xac\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2‘.decode("utf-8")
‘这是一个文本字符串‘

其中decode()与encode()方法可以接受参数,其声明分别为

bytes.decode(encoding="utf-8", errors="strict")
str.encode(encoding="utf-8", errors="strict")

其中的encoding是指在解码编码过程中使用的编码(此处指“编码方案”是名词),errors是指错误的处理方案

udp绑定端口问题(重点)

会变的网络端口

1. 每次重新运行一次网络程序,下图中红圈的数字都会变化,变化的原因在于,由于程序没有绑定固定的端口号 (socket.bind()) 所以系统会随机分配一个空闲的端口
2. 客户端一般是不需要使用 socket.bind() 绑定一个地址的,因为客户端进程存活时间相对较短,且客户端套接字为主动套接字,服务器在接收数据时动态地获取客户端地址已能满足需求 => 所以客户端程序不需要绑定固定端口号,有系统随机分配即可
3. 一个udp网络程序,可以不不绑定端口号,此时操作系统会随机进行分配一个端口,如果重新运行此程序端口会发生变化; 也可以进行端口的绑定,这样就是固定使用这个端口号

技术图片

全双工,半双工,单工

举几个简单例子来理解概念

1. 单工: 收音机  (只能是 A => B)
2. 半双工: 对讲机 (可以实现A <=> B,但是在A => B或者B => A的时候,另外一方是不能发送的)
3. 全双工: 电话 (A<=>B 同一时刻既可以收又可以发)   [socket是全双工特性的]

udp聊天器

# code04_udp聊天室_服务器.py

import socket


def main():
    # 创建socket
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 地址绑定
    udp_socket.bind(("", 3456))
    # 接收数据并打印
    print("-" * 10 + "聊天室" + "-" * 10)
    while True:
        recv_info = udp_socket.recvfrom(1024)
        address = f"{recv_info[1][0]}:{recv_info[1][1]}"
        print(address)
        print(recv_info[0].decode("gbk"))
    # 关闭socket
    udp_socket.close()


if __name__ == "__main__":
    main()


# code05_udp聊天室_客户端.py
import socket


def main():
    # 创建socket
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 向服务器发送数据
    print("-" * 10 + "输入框" + "-" * 10)
    while True:
        data = input()
        client_socket.sendto(data.encode("gbk"), ("localhost", 3456))
        if data.strip() in ("exit", "quit"): break
    # 关闭socket
    client_socket.close()


if __name__ == "__main__":
    main()

技术图片

网络tcp

TCP可以理解为"打电话"

tcp简介

tcp介绍

1. TCP协议,传输控制协议(Transmission Control Protocol,缩写为 TCP).
2. TCP是一种 面向连接的, 可靠的,基于 字节流 的 传输层 通信协议.
3. TCP通信需要经过 (1)创建连接 (2) 数据传送 (3) 终止连接 三个步骤.
    (1) TCP通信模型中,在通信开始之前,一定要先监理相关的链接,才能发送数据,类似于生活中"打电话".

tcp特点

1. 面向连接
    (1) 通信双方必须建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输.
    (2) 双方的数据传输都可以通过这一个连接进行.
    (3) 完成数据交换后,双方必须断开此连接,以释放系统资源.
    (4) 这种连接时一对一的, 因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议.

2. 可靠传输
    (1) TCP采用发送应答机制
        (a) TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功.
    (2) 超时重传
        (a) 发送段发出一个报文段之后就启动定时器,如果在定时时间内没有受到应答就重新发送这个报文段.
        (b) TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包按序接收. 然后接收端实体对已成功受到的包发挥一个相应的确认(ACK); 如果发送段实体在合理的往返时延(RTT)内未收到确认,那么对一个的数据包就被假设为已丢失,将会被进行重传.        
        (c)前面的两点,可以形象理解为打电话,然后A说话,B一定时间没有应答, 那么A就会重新在把刚才的话说多一次
        (d) 每次看电脑在下载一个东西,也有上传的数据,其实这个上传的数据就是TCP的应答数据.
    (3) 错误校验
        (a) TCP用一个校验和函数来检验数据是否有错误; 在发送和接收时都要计算校验和.
    (4) 流量控制和阻塞管理
        (a) 流量控制用来避免主机发送得过快而使接收方来不及完全收下.
        (b) 流量控制也是非常关键的,发送端50G的文件不能一股脑的发过来,要合理流量和控制,不然接收方不能成功接收.

TCP和UDP的不同点

TCP => 打电话
UDP => 写信

1. 面向连接(确认有创建三次握手,连接已创建才进行传输)
2. 有序数据传输
3. 重发丢失的数据包
4. 舍弃重复的数据包
5. 无差错的数据传输
6. 阻塞/流量控制

UDP通信模型
技术图片

TCP通信模型
技术图片

tcp网络程序-客户端(重点)

tcp客户端

1. tcp是严格区分客户端和服务器的
2. 所谓的服务器端,就是提供服务的一方,而客户端,就是需要被服务的一方.

tcp客户端构建流程

1. tcp的客户端比服务器端简单很多
2. 如果说服务器端是需要自己买手机,插电话卡,设置铃声,等待别人打电话这些样的流程,那么客户端就只需要找一个电话亭,拿起电话拨打即可,流程要少很多.

# code06_tcp_client.py
import socket


def main():
    # 创建tcp的套接字
    tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 链接服务器
    # 使用 socket.connect() 来链接服务器
    server_ip = input("请输入服务器ip: ").strip()
    server_port = int(input("请输入服务器port: ").strip())
    server_addr = (server_ip,server_port)
    tcp_socket.connect(server_addr)

    # 发送数据/接收数据
    # 这里已经建立了通道,所有使用 socket.send()   UDP 使用 socket.sendto()
    while True:
        send_data = input("请输入要发送的数据(exit): ").strip()
        if send_data == "exit":break
        tcp_socket.send(send_data.encode("gbk"))

    # 关闭套接字
    tcp_socket.close()

if __name__ == "__main__":
    main()


技术图片

tcp网络程序-服务端(重点)

tcp是严格区分客户端和服务器的

tcp服务器

用电话机的过程来理解tcp服务器端
1. 买个手机 <=> socket创建一个套接字
2. 插上手机卡 <=> bind绑定ip和port
3. 设置手机为正常接听状态(即能够响铃) <=> listen使套接字变为被动链接
4. 静静的等待别人拨打 <=> accept等待客户端的连接
5. 进行通话 <=> recv/send 接收发送数据

tcp注意点(重点)

案例: 文件下载器

tcp的3次握手

tcp的4次挥手

tcp长连接和短连接

网络编程

标签:说话   控制   占用   可靠传输   理解   ftp服务   客户端程序   元组   通话   

原文地址:https://www.cnblogs.com/Rowry/p/12709511.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!