Python复习笔记(六)网络编程(udp/tcp)

时间:2022-09-18 21:23:09

一、网络-udp(用户数据报协议)

  • 用户数据报协议

  • 类似写信,不安全,数据有可能丢

1.1 ip地址

Python复习笔记(六)网络编程(udp/tcp)

Python复习笔记(六)网络编程(udp/tcp)

Python复习笔记(六)网络编程(udp/tcp)

Python复习笔记(六)网络编程(udp/tcp)

注意:

IP地址127.0.0.1 ~ 127.255.255.255 用于回路测试

私有ip地址,不在公网中使用


1.2 端口(重点)

  • 端口是通过端口号来标记的,端口号只有整数,范围是从0~65535(2^16)
  • 知名端口:(0~1023)(>1024的随便用)
    • 80端口 分配给 HTTP 服务
    • 21端口 分配给 ftp 服务
  • 动态端口(1024~65535)

1.3 socket简介

1.31 不同电脑上进程之间如何通信

  • 利用 ip地址、协议、端口 就可以标识网络的进程了。
  • 进程间通信:运行的程序之间的数据共享。

1.32 创建socket

在Python中 使用socket 模块的函数 socket就可以完成:、

import socket

# AddressFamily: ipv4/ipv6; Type: udp/tcp
socket.socket(AddressFamily, Type)

说明:

函数 socket.socket 创建一个 socket,该函数带有两个参数:

  • Address Family:可以选择 AF_INET (用于Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作常用 AF_INET

  • Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于TCP协议)或者 SOCK_DGRAM(数据报套接字,主要用于UDP协议)

创建一个 tcp socket (tcp套接字)

import socket

# AddressFamily: ipv4/ipv6; Type: udp/tcp

# 创建tcp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # ... 这里是使用套接字的功能 (省略) # 不用的时候,关闭套接字
s.close()

创建一个 udp socket (udp 套接字)

import socket

# AddressFamily: ipv4/ipv6; Type: udp/tcp

# 创建tcp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # ... 这里是使用套接字的功能 (省略) # 不用的时候,关闭套接字
s.close()

说明

  • 套接字使用流程
    1. 创建套接字
    2. 使用套接字收/发数据
    3. 关闭套接字

1.4 udp网络程序-发送、接收数据

1.41 udp网络程序-发送程序

import socket

# AddressFamily: ipv4/ipv6; Type: udp/tcp

# 1. 创建udp的套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 2. 准备接收方地址
# '192.168.43.74' 表示目标ip地址
# 8080表示目的端口
dest_addr = ('192.168.43.74', 8080) # 注意 是元组,ip是字符串,端口是数字 # 3. 从键盘获取数据
send_data = input("请输入要发送的数据:") # 4. 发送数据到指定的电脑上的指定程序中
udp_socket.sendto(send_data.encode('utf-8'), dest_addr) # 不用的时候,关闭套接字
udp_socket.close()

Python复习笔记(六)网络编程(udp/tcp)

注意:可以用NetAssist测试

1.42 udp网络程序—接收程序 (绑定实例)

# -*- coding: utf-8 -*-
"""
Created on Fri Mar 1 22:25:32 2019 @author: Douzi
""" import socket def main():
# AddressFamily: ipv4/ipv6; Type: udp/tcp # 1. 创建udp的套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 2. 绑定一个本地信息 '192.168.43.74'
local_addr = ("", 7788) # 注意 是元组,ip是字符串,端口是数字
udp_socket.bind(local_addr) # 必须绑定自己电脑的ip以及port,其他的不行 # 3. 等待接收对方发送的数据
recv_data = udp_socket.recvfrom(1024) #1024表示本次接收的最大字节数
# recv_data这个变量中存储的是一个元组(接收到的数据, (发送方ip, port))
recv_msg = recv_data[0]
send_addr = recv_data[1] # 4. 显示接收到的数据------------
print(recv_data)
print(recv_msg.decode("gbk"))
print(send_addr) # 关闭套接字
udp_socket.close() if __name__=="__main__":
main()

Python复习笔记(六)网络编程(udp/tcp)

Python复习笔记(六)网络编程(udp/tcp)

1.43 聊天程序

# -*- coding: utf- -*-
"""
Created on Sat Mar :: @author: Douzi
""" import socket def send_msg(udp_socket):
"""发送消息"""
# 获取内容
dest_ip = input("输入ip: ")
dest_port = int(input("输入对方port:"))
send_data = input("输入发送数据:")
udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port)) def recv_msg(udp_socket):
recv_data = udp_socket.recvfrom()
print("%s:%s " % (str(recv_data[]), recv_data[].decode("utf-8"))) def main():
# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 绑定信息
udp_socket.bind(("", )) # '192.168.43.74' while True: print("0----发送消息")
print("1----接收消息")
print("2----退出")
op = input("输入功能: ") if op == "":
# 发送
send_msg(udp_socket)
elif op == "":
# 接收并显示
recv_msg(udp_socket)
else:
return if __name__=="__main__":
main()

二、TCP

2.1 简介(传输控制协议)

  • TCP协议,传输控制协议(Transmission Control Protocol)
  • 类似打电话
  • TCP通信需要经过 创建连接、数据传送、终止连接 三个步骤。

2.2 特点(安全复杂)

1. 面向连接

2. 可靠传输

  • TCP采用发送应答机制
  • Python复习笔记(六)网络编程(udp/tcp)
  • 超时重传

    • 发送端发出一个报文段之后,就 启动定时器,如果在定时时间没有收到应答就重新发送这个报文段

    • TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的 按序接收,然后 接收端实体 对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的 往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失,将会进行重传。

  • 错误校验

    • TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
  • 流量控制和阻塞管理

    • 流量控制用来避免主机发送得快而使接收方来不及完全收下

 TCP和UDP的不同点

  • 面向连接(确认有创建三方交握,连接已创建才做传输)

  • 有序数据传输

  • 重发丢失的数据包

  • 舍弃重复的数据包

  • 无差错的数据传输

  • 阻塞/流量控制


2.3 tcp客户端(重点)

2.31 tcp客户端构建流程

示例代码:

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 3 14:14:03 2019 @author: Douzi
""" import socket def main():
# 1.创建socket
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2.链接服务器
# server_ip = input("输入服务器ip:")
# server_port = int(input("输入服务器port:"))
# tcp_client_socket.connect((server_ip, server_port))
tcp_client_socket.connect(("192.168.43.74", 8080)) # 提示用户输入数据
send_data = input("输入数据: ") tcp_client_socket.send(send_data.encode("gbk")) # 接收对方发送过来的数据,最大接收1024个字节
recvData = tcp_client_socket.recv(1024) print("接收到的数据: ", recvData.decode("gbk")) # 关闭套接字
tcp_client_socket.close() if __name__=="__main__":
main()

2.4 tcp服务器(重点)

流程如下:

1. socket创建一个套接字

2. bind绑定ip和port

3. listen使套接字变为 可以被动链接(监听套接字 负责 等待有新的客户端进行链接)

4. accept等待客户端的链接 (accept 产生新的套接字 用来为客户端服务)

5. recv/send接收发送数据

一个简单的tcp服务器如下:

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 3 14:55:42 2019 @author: Douzi
""" import socket def main():
# 创建套接字
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定本地信息 bind
tcp_socket_server.bind(("192.168.43.74", 6677))
# 让默认的套接字由主动变为被动 listen,这样就可以接收别人的链接了
tcp_socket_server.listen(128)
# 等待客户端的链接accept
# client_socket用来为这个客户端服务
# tcp_socket_server就可以省下来专门等待其他新客户端的链接
client_socket, clientAddr = tcp_socket_server.accept() # 接收对方发送过来的数据
recv_data = client_socket.recv(1024) # 接收1024个字节
print('接收到的数据: ', recv_data.decode('gbk')) # 发送一些数据到客户端
client_socket.send("Douzi is cute".encode('gbk')) # 关闭套接字
client_socket.close() if __name__=="__main__":
main()

Python复习笔记(六)网络编程(udp/tcp)

Python复习笔记(六)网络编程(udp/tcp)

Python复习笔记(六)网络编程(udp/tcp)

为多个客户端服务

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 3 14:55:42 2019 @author: Douzi
""" import socket def main():
# 创建套接字(买个手机)
tcp_socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定本地信息 bind (插入手机卡)
tcp_socket_server.bind(("192.168.43.74", 6677))
# (将手机设置为响铃)让默认的套接字由主动变为被动 listen,这样就可以接收别人的链接了
tcp_socket_server.listen(128) while True:
print("等待一个新的客户端的到来....")
# 等待客户端的链接accept (等待别人的电话)
# client_socket用来为这个客户端服务
# tcp_socket_server就可以省下来专门等待其他新客户端的链接
client_socket, client_addr = tcp_socket_server.accept() print(client_addr) # 为同一个客户端服务多次
while True:
# 接收对方发送过来的数据
recv_data = client_socket.recv(1024) # 接收1024个字节
print('接收到的数据: ', recv_data.decode("gbk")) # 如果recv 解堵塞,那么有2种方式:
# 1. 客户端发送过来数据
# 2. 客户端调用close导致了 这里recv解堵塞
if recv_data:
# 回送一部分数据到客户端
client_socket.send("Douzi is cute".encode('gbk'))
else:
break # 关闭套接字
client_socket.close() print("已经服务完毕....") tcp_socket_server.close() if __name__=="__main__":
main()

Python复习笔记(六)网络编程(udp/tcp)


2.5 案例:文件下载器

文件下载的服务器

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 3 17:46:37 2019 @author: Douzi
""" import socket
import sys def get_file_content(file_name):
"""获取文件内容"""
try:
with open(file_name, "rb") as f:
content = f.read()
return content
except:
print("没有下载的文件: %s" % file_name) def main(): if len(sys.argv) != 2:
print("请按如下方式运行: python3 xxx.py 7890")
return
else:
# 运行方式
port = int(sys.argv[1]) # 创建socket
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 本地信息, port: 7890
address = ("192.168.43.74", port)
# 绑定本地信息
tcp_server_socket.bind(address)
# 将主动套接字变为被动套接字
tcp_server_socket.listen(128) while True:
# 等待客户端的链接,即为这个客户端发送文件
client_socket, client_addr = tcp_server_socket.accept()
# 接收对方发送过来的数据
recv_data = client_socket.recv(1024)
file_name = recv_data.decode("utf-8")
print("客户端需要下载的文件名为:%s" % file_name) file_content = get_file_content(file_name)
# 发送文件的数据给客户端
# 因为获取打开文件时是以rb方式打开,所以file_content中的数据已经是二进制的格式
# 所以不需要encode
if file_content:
client_socket.send(file_content)
# 关闭这个套接字
client_socket.close()
isOK = input("继续吗?Y/N")
if isOK == "Y":
break # 关闭监听套接字
tcp_server_socket.close() if __name__=="__main__":
main()

文件下载的客户端

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 3 19:34:20 2019 @author: Douzi
""" import socket def main(): # 创建socket
tcp_socket_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 目的信息
server_ip = "192.168.43.74" # 服务器的ip
server_port = 7891 # 服务器的port # 链接服务器
tcp_socket_client.connect((server_ip, server_port)) # 输入需要下载的文件名
file_name = input("输入要下载的文件名: ") # 发送文件下载请求
tcp_socket_client.send(file_name.encode("utf-8")) # 接收对方发送过来的数据,最大接收1024个字节 (1k)
# 1024--1k, 1024*1024--1M,1024*1024*1024--1G
recv_data = tcp_socket_client.recv(1024*1024) # print('接收到的数据', recv_data.decode('utf-8'))
# 如果接收到数据再创建文件,否则不创建
if recv_data:
with open("[接收]"+file_name, "wb") as f:
f.write(recv_data) # 关闭套接字
tcp_socket_client.close() if __name__=="__main__":
main()

Python复习笔记(六)网络编程(udp/tcp)


2.6 tcp注意点

  • tcp服务器 一般需要绑定,否则客户端找不到这个服务器

  • tcp客户端 一般不绑定,因为是主动链接服务器,所以只要确定好服务器的ip,port等信息就好,本地客户端可随意

  • tcp服务器通过listen可以将socket创建出来的主动套接字变成被动的,这是做tcp服务器必须要做的

  • 当客户端需要链接服务时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务

  • listen后的套接字是被动套接字,用来接收 新的客户端 的链接请求,而accept返回的新套接字,是标记这个新客户端的。

  • 关闭 listen 后的套接字 意味着 被动套接字被关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信

  • 关闭 accept 返回的套接字意味着这个客户端已经服务完毕。

  • 当客户端的套接字 调用close后,服务器端会recv解阻塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线。

udp tcp:client tcp:server
socket         socket    socket
bind connect bind()
sendto/recvfrom send/recv listen(128)
close close accept: client_socket, client_addr
    recv/send
    close

三. tcp的3次握手、4次挥手(重点 !)

  • syn:标记请求的第一次
  • ack:应答

3.1 3次握手

业务开始(客户端先请求)

Python复习笔记(六)网络编程(udp/tcp)

3.2 4次挥手

业务结束后,关闭(客户端先关)

Python复习笔记(六)网络编程(udp/tcp)

服务器先关闭,需要等待2-5分钟

设置当前服务器先close 即服务器4次挥手后资源能够立即是否,这样就保证了。下次运行程序时,可以立即执行

tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

Python复习笔记(六)网络编程(udp/tcp)

Python复习笔记(六)网络编程(udp/tcp)的更多相关文章

  1. python学习笔记11 ----网络编程

    网络编程 网络编程需要知道的概念 网络体系结构就是使用这些用不同媒介连接起来的不同设备和网络系统在不同的应用环境下实现互操作性,并满足各种业务需求的一种粘合剂.网络体系结构解决互质性问题彩是分层方法. ...

  2. python学习笔记10 ----网络编程

    网络编程 网络编程需要知道的概念 网络体系结构就是使用这些用不同媒介连接起来的不同设备和网络系统在不同的应用环境下实现互操作性,并满足各种业务需求的一种粘合剂.网络体系结构解决互质性问题彩是分层方法. ...

  3. java 网络编程 UDP TCP

    网络编程 网络编程主要用于解决计算机与计算机(手机.平板..)之间的数据传输问题. 网络编程: 不需要基于html页面就可以达到数据之间的传输. 比如: feiQ , QQ , 微信....网页编程: ...

  4. python学习笔记(六) 函数式编程

    一 函数对象 函数同样可以作为对象复制给一个变量,如下: f = abs; print(f(-10)) f = 'abs'; print(f) def add(a,b,f): return f(a) ...

  5. 【网络编程1】网络编程基础-TCP、UDP编程

    网络基础知识 网络模型知识 OSI七层模型:(Open Systems Interconnection Reference Model)开放式通信系统互联参考模型,是国际标准化组织(ISO)提出的一个 ...

  6. python网络编程05 /TCP阻塞机制

    python网络编程05 /TCP阻塞机制 目录 python网络编程05 /TCP阻塞机制 1.什么是拥塞控制 2.拥塞控制要考虑的因素 3.拥塞控制的方法: 1.慢开始和拥塞避免 2.快重传和快恢 ...

  7. Socket网络编程-UDP编程

    Socket网络编程-UDP编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.UDP编程概述 1>.UDP服务端编程流程 创建socket对象.socket.SOCK_ ...

  8. C#网络编程之---TCP协议的同步通信(二)

    上一篇学习日记C#网络编程之--TCP协议(一)中以服务端接受客户端的请求连接结尾既然服务端已经与客户端建立了连接,那么沟通通道已经打通,载满数据的小火车就可以彼此传送和接收了.现在让我们来看看数据的 ...

  9. 嵌入式linux的网络编程(1)--TCP/IP协议概述

    嵌入式linux的网络编程(1)--TCP/IP协议概述 1.OSI参考模型及TCP/IP参考模型 通信协议用于协调不同网络设备之间的信息交换,它们建立了设备之间互相识别的信息机制.大家一定都听说过著 ...

随机推荐

  1. Java引用机制——reference

    所谓引用传递就是指将堆内存空间的使用权交给多个栈内存空间. 例子<1> public class Aliasing { int temp = 30; public static void ...

  2. htaccess 探秘

    .htaccess访问控制(Allow/Deny) 1. 验证是否支持.htaccess 在目录下新建一个.htaccess 文件,随笔输入一串字符(毫无意义),看看什么反应,如果是500错误,说明目 ...

  3. Linux多线程之互斥

    题目 共要卖票20张,由命令行输入窗口数,由线程模拟窗口.每卖掉一张票,屏幕显示由几号窗口所卖,一并显示剩余票数 思路 由于票数 ticket_cnt 是全局变量,因此每当一个线程将其减一(卖出一张票 ...

  4. 武汉科技大学ACM :1005&colon; C语言程序设计教程(第三版)课后习题6&period;6

    Problem Description 打印出所有"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该本身. 例如:153是一个水仙花数,因为1 ...

  5. C&plus;&plus;中 指针 与 引用 的区别

    四点区别:可否为空,可否修改,使用时是否需要判断,使用场景 非空区别. 引用必须指向某个对象,而指针可以指向空. 可修改区别. 引用总是与初始化时的那个对象绑定,不可变更:指针可以重新赋值,指向另外一 ...

  6. zTree理解和简单Demo(转)

    zTree是利用 jQuery 的核心代码,实现一套能完成大部分常用功能的 Tree 插件.整个zTree的页面显示核心 代码是. <span style="font-family:V ...

  7. MySql数据库导入导出

    1.导出整个数据库     mysqldump -u 用户名 -p 数据库名 > 存放位置     比如:     mysqldump -u root -p project > c:/a. ...

  8. lua 函数调用1 -- 闭包详解和C调用

    这里, 简单的记录一下lua中闭包的知识和C闭包调用 前提知识: 在lua api小记2中已经分析了lua中值的结构, 是一个 TValue{value, tt}组合, 如果有疑问, 可以去看一下 一 ...

  9. CentOS6&period;8 使man支持显示中文

    1.安装显示中文的man命令 wget https://src.fedoraproject.org/repo/pkgs/man-pages-zh-CN/manpages-zh-1.5.1.tar.gz ...

  10. 深度解析:python之浅拷贝与深拷贝

    深度解析python之浅拷贝与深拷贝 本文包括知识点: 1.copy与deepcopy 2.可变类型与不可变类型 1.copy与deepcopy 在日常python编码过程中,经常会遇见变量的赋值.这 ...