1.TCP

2.补充异常处理

3.UDP

一TCP.
1.socket基础版本通讯

服务端:

 1 import socket
 2
 3 server = socket.socket()# 生成一个对象
 4 server.bind(('127.0.0.1',8080))# 绑定ip和端口
 5 server.listen(5)# 连接池
 6
 7 conn,addr = server.accept()# 等待别人 一个是ip 一个是地址  阻塞
 8 data = conn.recv(1024) # 听别人说话   阻塞
 9 print(data)
10 conn.send(b'hello boby')# 给对方回信息
11
12 conn.close()# 断开链接
13 server.close()# 结束掉进程

View Code

客户端:

 1 import socket
 2
 3
 4 client = socket.socket()# 生成一个对象
 5
 6 client.connect(('127.0.0.1',8080))# 发送你的ip和端口号
 7
 8 client.send(b'hello word')# 对别人说话
 9 data = client.recv(1024) # 听别人说话
10 print(data)
11
12 client.close()# 断开链接

View Code

2 升级版实现多条通讯

服务端:

 1 import socket
 2
 3 server = socket.socket() # 创建一个对象
 4 server.bind(('127.0.0.1',8989)) # 绑定 ip 和端口
 5 server.listen(5)# 最大连接数
 6
 7 while True:
 8     conn,addr = server.accept() # 等待 别人链接进来  ip和端口 # 等到别人来  conn就类似于是双向通道
 9     print(conn)
10     print(addr)## ('127.0.0.1', 51323) 客户端的地址
11     while True:
12         try:
13             data = conn.recv(1024)# 接收数据
14             # 判断接收的数据为不为空
15             if not data:break## b''  针对mac与linux 客户端异常退出之后 服务端不会报错 只会一直收b''
16             conn.send(data.upper())
17         except ConnectionResetError as e:
18             print(e)
19             break
20     conn.close()

View Code

客户端:

 1 import socket
 2
 3 client = socket.socket() # 创建一个对象
 4 client.connect(('127.0.0.1',8989))# 写入要链接的ip 和端口号
 5
 6 while True:
 7     msg = input('请输入:>>>').encode('utf-8')# 发送数据
 8     # 判断数据是否为空
 9     if not msg:continue
10     client.send(msg)
11     # 接收数据
12     data = client.recv(1024)
13     print(data)

View Code

tcp的沾包问题

客户端:

import time
import socketclient = socket.socket()
client.connect(('127.0.0.1',8080))client.send(b'hello')
# time.sleep(5)
client.send(b'word')

服务端:

import socketserver =  socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
conn,addr = server.accept()data = conn.recv(5)
print(data)
data = conn.recv(5)
print(data)'''
可以规定接收的数据长度,但是你不知道对方每次要发多少数据,这个接收数据的1024不能随便改,所以说要想其他的方法
解决方案就是你要提前告知收方数据的长度
'''

那么沾包是如何产生的:

TCP流式协议, 数据之间没有分界, 就像水  一杯水和一杯牛奶倒在一起了!UDP 用户数据报协议    粘包 仅发生在TCP协议中   1. 发送端 发送的数据量小 并且间隔短 会粘
2. 接收端 一次性读取了两次数据的内容    会粘
3. 接收端 没有接收完整  剩余的内容 和下次发送的粘在一起无论是那种情况,其根本原因在于  接收端不知道数据到底有多少 解决方案就是 提前告知接收方 数据的长度  

那么如何解决沾包:

.TCP粘包问题
struct模块 对数据进行打包处理 固定长度
pack
unpack

服务端
1.生成一个字典
2.制作该字典的报头
json序列化
编码 统计长度
3.发送字典的报头
4.发送字典
5.最后发真实数据

客户端
1.先接受固定长度的4个字节字典报头
2.解析获取字典数据的长度
unpack(...)[0]
3.接受字典数据
解码 反序列化
4.接受真实数据

ps:为什么要多加一个字典
1.打包的数据大小有限
2.可以携带更多的信息

代码实现解决沾包问题:
客户端:

 1 import socket
 2 import struct
 3 import json
 4
 5 client = socket.socket()
 6 client.connect(('127.0.0.1',8080))
 7
 8 while True:
 9     msg = input('msg:>>>').encode('utf-8')
10     if not msg:continue
11     client.send(msg)
12     # 接收字典报头
13     header = client.recv(4)
14     # 解析报头,拿到真实的数据长度
15     header_dict = struct.unpack('i',header)[0]
16     # 接收字典数据
17     dict_bytes = client.recv(header_dict)
18     json_dict = json.loads(dict_bytes.decode('utf-8'))
19     # 从字典中获取信息
20     print(json_dict)
21     recv_size = 0
22     real_data = b''
23     # 循环接收字典中的信息
24     while recv_size < json_dict.get('file_size'):
25         data = client.recv(1024)
26         recv_size +=len(data)
27         real_data +=data
28         print(data.decode('gbk'))
29         print(recv_size)

View Code

服务端:

 1 import socket
 2 import struct
 3 import json
 4 import subprocess
 5
 6 server = socket.socket()
 7 server.bind(('127.0.0.1',8080))
 8 server.listen(5)
 9
10 while True:
11     conn,addr = server.accept()
12     while True:
13         try:
14             cmd = conn.recv(1024)
15             if not cmd:break
16             cmd = cmd.decode('utf-8')
17             obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
18             res = obj.stdout.read()+obj.stderr.read()
19             # 定义一个字典
20             d = {'name':'zy','file_size':len(res)}
21             json_d = json.dumps(d)
22             #1.制作字典报头
23             header = struct.pack('i',len(json_d))
24             #2. 发送字典报头
25             conn.send(header)
26             #3.发送字典
27             conn.send(json_d.encode('utf-8'))
28             #4.发送正式数据
29             conn.send(res)
30         except ConnectionResetError as e:
31             print(e)
32             break
33     conn.close()

View Code

补充:

解决沾包问题需要用到的struct模块:

 1 import struct
 2 #
 3 # res = 'dgbdushfgcbdsjhgbcshjdgcbidjhgvKADJFCNalskCNkfjcnLJCHSDNCKLSD'
 4 # print('最开始的',len(res))
 5 #
 6 # res1 = struct.pack('i',len(res))
 7 # print('打包好的',len(res1))
 8 #
 9 # res2 = struct.unpack('i',res1)[0] # 如果不加索引解包后的结果就是解包后的 (61,),索引拿到的是0号位
10 # print('解包后的',res2)
11
12
13
14 '''
15  当原始数据特别大的时候 i模式打包不了 需要更换模式?
16  如果遇到数据量特别大的情况 该如何解决?
17  可以定义一个字典
18 '''
19 d = {
20     'name':'zy',
21     'file_size':'123473985961732617417324627346723641746723462374613274164',
22     'info':'你好',
23 }
24
25 import json
26 json_d = json.dumps(d)
27 print(len(json_d))
28
29 res1 = struct.pack('i',len(json_d))
30 print(len(res1))
31
32 res2 = struct.unpack('i',res1)[0]
33 print('解包后的数据',res2)

View Code

补充:复习subprocess模块

 1 import subprocess
 2
 3 while True:
 4     cmd = input('cmg:>>>')
 5     if cmd == 'q':break
 6     if not cmd:continue
 7     obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
 8     print(obj.stdout.read().decode('gbk'))# 正确命令返回的结果
 9     print(obj.stderr.read().decode('gbk'))# 错误的命令返回的结果
10
11 #注意:subprocess获取到的数据,拿完就没有了,不能重复的拿

View Code

练习:大文件上传:

客户端:

 1 mport struct
 2 import json
 3 import socket
 4 import os
 5
 6 client = socket.socket()
 7 client.connect(('127.0.0.1',8080))
 8
 9 while True:
10     # 获取文件路径
11     MOVIE_DIR = r'H:\python视频\python10期\day29\视频'
12     # 显示文件里的电影
13     movie_list = os.listdir(MOVIE_DIR)
14     # 循环打印电影
15     for i,movie in enumerate(movie_list,1):
16         print(i,movie)
17     # 选取电影
18     choice = input('请选择电影:>>>').strip()
19     if choice.isdigit():
20         choice = int(choice)-1
21         # 判断是否在索引范围内
22         if choice in range(0,len(movie_list)):
23             # 获取要上传电影的文件路径
24             path = movie_list[choice]
25             # 获取要上传电影的绝对路径,拼接
26             file_path = os.path.join(MOVIE_DIR,path)
27             # 获取文件的大小
28             file_size = os.path.getsize(file_path)
29             # 定义一个字典
30             d = {
31                 'file_name':'qwer.mp4',
32                 'file_size':file_size,
33             }
34             # 序列化字典
35             json_d = json.dumps(d)
36             json_bytes = json_d.encode('utf-8')
37             # 制作字典报头
38             header = struct.pack('i',len(json_bytes))
39             # 发送字典报头
40             client.send(header)
41             # 发送字典数据
42             client.send(json_bytes)
43             # 循环发送文件数据
44             with open(file_path,'rb') as f:
45                 for line in f:
46                     client.send(line)
47         else:
48             print('序号不在索引范围内')
49     else:
50         print('请输入数字')

View Code

服务端:

 1 import socket
 2 import struct
 3 import json
 4
 5
 6 server = socket.socket()
 7 server.bind(('127.0.0.1',8080))
 8 server.listen(5)
 9
10 while True:
11     conn,addr = server.accept()
12     while True:
13         try:
14             # 先接收报头
15             header = conn.recv(4)
16             # 解析字典报头
17             header_len =struct.unpack('i',header)[0]
18             # 接收字典数据
19             json_bytes = conn.recv(header_len)
20             json_dict = json.loads(json_bytes.decode('utf-8'))
21             # 获取字典长度
22             len_size = json_dict.get('file_size')
23             # 循环接收文件数据
24             recv_size = 0
25             with open(json_dict.get('file_name'),'wb') as f:
26                 while recv_size < len_size:
27                     data = conn.recv(1024)
28                     f.write(data)
29                     recv_size+=len(data)
30                 print('上传成功')
31                 print(recv_size)
32         except ConnectionResetError as e:
33             print(e)
34             break
35     conn.close()

View Code

二.异常处理

什么是异常处理:

  程序在运行过程中出现了不可预知的错误,并且该程序没有对应的处理机制’,

  那么就会以异常的形式表示出来,造成的影响就是整个程序无法在正常运行了,

  那么我们一般不建议使用异常处理,一般的异常都是可以通过修改代码可以防止

  出现异常的,只有那么你知道会报错,而不能解决的,

  举例:比如说你和别人在打电话,那么可能会出现一些意外,可能手机关机了,或者没信号了

  所以说在无法解决的时候在使用异常处理

异常的结构:

  1.异常的类型:NAMEERROR

  2.异常的信息:name 'fdsdfsdf' is not defined

  3.异常的位置:Traceback (most recent call last):
  File "D:/python脱产10期视频/day29/01 异常处理.py", line 1, in <module>
  fdsdfsdf

异常的种类:

  分为俩大类:

    1.语法上的错误:

      是你程序启动立刻就能解决的,这种错误也是不能被容忍的,

      语法上的错误,发现之后应该立即解决

    2.逻辑上的错误:

      这种错误是可以被容忍的,因为一眼看不出来,

      针对逻辑上的错误,可以采用异常处理机制进行捕获

    

    常见的错误类型:

      NAMERROR 名字错误

      SyntaxError 语法错误
      eyError 键不存在
      ValueError 值错误
      IndexError 索引错误

  如何避免:

    异常处理:

      在你认为可能会出现的bug的代码上方try一下:注意try内部的代码块越少越好

      try:

        可能出现的错误

      except 出错的类型 as e: 将报错信息赋值给变量

        出错之后的处理机制

三.UDP协议

udp协议简介

用户数据报协议,是OSI模型中属于传输层的协议

提供,不可靠的,不要求顺序的,数据量小的,速度快的传输服务

不可靠:

发送完成后不需要确认信息 并且立即删除缓存中的数据

不要求顺序:

当一个数据较大时 会分为多个数据报来传输,对方无法获知数据的顺序,以及是否完整

数据量较小的:

数据越大丢包的可能性越高 ,建议的数据量不要超过1472

速度快:

相对于TCP而言快很多 不需要确认信息 ,也不需要建立链接

udp协议的通讯流程:

如果TCP比喻为手机打电话的过程 那么UDP可以看做是对讲机

1.买机器 创建UDP的socket

2.固定频道 bind一个ip和端口

3.收发数据 recvfrom sendto

接收

1.买机器 创建UDP的socket

2.收发数据 recvfrom sendto

注意 不能先收 要收数据 必须明确端口号 没有端口号是不可能使用网络服务的

TCP 与 UDP 的其他区别

1.没有连接

2.不会粘包 每次发送都是一个独立的数据包

TCP 对数据完整性要求较高 : 在线支付 ,文字信息

UDP: 对数据不要求完整性 但是要快 : 视频 语音 游戏

udp协议的基本使用:

服务端:

 1 import socket
 2
 3 server = socket.socket(type=socket.SOCK_DGRAM)# UDP协议
 4 server.bind(('127.0.0.1',8080))
 5 '''
 6 UDP不需要设置半链接池,它也没有半连接池的概念
 7 因为没有双向通道,不需要accept 直接就是通信循环
 8 '''
 9 while True:
10     data,addr = server.recvfrom(1024)
11     print('数据',data)# 客户端发来的信息
12     print('地址',addr)# 客户端发来的地址
13     server.sendto(data.upper(),addr)
14     break

View Code

客户端:

 1 import socket
 2
 3 client = socket.socket(type=socket.SOCK_DGRAM)
 4 #不需要建立链接,直接进入通信循环
 5 server_address = ('127.0.0.1',8080)
 6
 7 while True:
 8     client.sendto(b'hello',server_address)
 9     data,addr = client.recvfrom(1024)
10     print('服务端发来的数据',data)
11     print('服务端发来的地址',addr)
12     break

View Code

udp通讯是不会沾包的:

服务端:

 1 import socket
 2
 3 server = socket.socket(type=socket.SOCK_DGRAM)
 4 server.bind(('127.0.0.1',8080))
 5
 6 data,addr = server.recvfrom(1024)
 7 print(data)
 8 data,addr1 = server.recvfrom(1024)
 9 print(data)
10 data,addr2 = server.recvfrom(1024)
11 print(data)

View Code

客户端:

1 import socket
2
3
4 client = socket.socket(type=socket.SOCK_DGRAM)
5 server_address = ('127.0.0.1',8080)
6
7 client.sendto(b'hello',server_address)
8 client.sendto(b'hello',server_address)
9 client.sendto(b'hello',server_address)

View Code

小练习:udp实现简易版本的qq

服务端:

 1 import socket
 2
 3 server = socket.socket(type=socket.SOCK_DGRAM)
 4 server.bind(('127.0.0.1',8080))
 5
 6
 7 while True:
 8     data,addr = server.recvfrom(1024)
 9     print(data.decode('utf-8'))
10     msg = input('msg:>>>').strip()
11     server.sendto(msg.encode('utf-8'),addr)

View Code

客户端1:

 1 import socket
 2
 3 client = socket.socket(type=socket.SOCK_DGRAM)
 4 server_address = ('127.0.0.1',8080)
 5
 6 while True:
 7     msg = input('msg:>>>').strip()
 8     msg = '来自客户端1的信息:%s'%msg
 9     client.sendto(msg.encode('utf-8'),server_address)
10     data,server_addr = client.recvfrom(1024)
11     print(data.decode('utf-8'))

View Code

客户端2:

 1 import socket
 2
 3 client = socket.socket(type=socket.SOCK_DGRAM)
 4 server_address = ('127.0.0.1',8080)
 5
 6 while True:
 7     msg = input('msg:>>>').strip()
 8     msg = '来自客户端2的信息:%s'%msg
 9     client.sendto(msg.encode('utf-8'),server_address)
10     data,server_addr = client.recvfrom(1024)
11     print(data.decode('utf-8'))

View Code

客户端3:

 1 import socket
 2
 3 client = socket.socket(type=socket.SOCK_DGRAM)
 4 server_address = ('127.0.0.1',8080)
 5
 6 while True:
 7     msg = input('msg:>>>').strip()
 8     msg = '来自客户端3的信息:%s'%msg
 9     client.sendto(msg.encode('utf-8'),server_address)
10     data,server_addr = client.recvfrom(1024)
11     print(data.decode('utf-8'))

View Code

转载于:https://www.cnblogs.com/zahngyu/p/11324021.html

网络编程之Tcp,udp相关推荐

  1. 网络编程之 TCP / UDP 及其流程比较

    TCP与UDP的区别 1.基于连接与无连接 2.对系统资源的要求(TCP较多,UDP少) 3.UDP程序结构较简单 流模式与数据报模式 4.TCP保证数据正确性,UDP可能丢包 5.TCP保证数据顺序 ...

  2. Java网络编程之TCP、UDP

    Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. J ...

  3. 网络编程之TCP协议与UDP对比

    网络编程之TCP协议与UDP对比 UDP协议: 1,面向无连接. 2,不可靠协议,容易丢包. 3,速度快. 4,包体积有限制,64k以内. 通常,聊天,在线视频,凌波. TCP协议: 1.面向连接. ...

  4. Python中的网络编程之TCP

    Python中的网络编程之TCP 文章目录 Python中的网络编程之TCP 1.TCP介绍 2.TCP特点 3.TCP与UDP的不同点 4.tcp通信模型 5.tcp客户端 6.tcp服务器 7.T ...

  5. java 网络编程简单聊天_网络编程之 TCP 实现简单聊天

    网络编程之 TCP 实现简单聊天 客户端 1.连接服务器 Socket 2.发送消息 package lesson02;import java.io.IOException;import java.i ...

  6. java网络编程之TCP通讯

    java中的网络编程之TCP协议的详细介绍,以及如何使用,同时我在下面举2例说明如何搭配IO流进行操作, 1 /* 2 *TCP 3 *建立连接,形成传输数据的通道: 4 *在连接中进行大数据量传输: ...

  7. Centos网络编程之tcp十一种状态及问题处理办法

    尊重原创版权: https://www.noveljp.com/hot/43730.html 更多内容参考: https://www.noveljp.com/ Linux网络编程之tcp十一种状态及问 ...

  8. 网络编程之TCP客户端程序开发

    网络编程之TCP客户端程序开发 1. 开发 TCP 客户端程序开发步骤 2. socket 类的介绍 3. TCP 客户端程序开发示例代码 4. 小结 1. 开发 TCP 客户端程序开发步骤 创建客户 ...

  9. Linux网络编程之TCP状态转移

    Linux网络编程之TCP状态转移 一.TCP状态转移时序 二.半关闭及shutdown函数 一.TCP状态转移时序 TCP状态转移图: netstat -apn | grep client 查看客户 ...

  10. Python编程(01)----网络编程之TCP/IP/UDP/Port等知识讲解

    一.首先明白什么是 UDP/TCP 1) 相同(目的一致):都是要完成PC之间的通信. 2) 不同: TCP:优点:可靠----TCP在传递数据之前,会有三次握手和四次挥手来建立连接和关闭连接.数据传 ...

最新文章

  1. Faiss教程:索引(2)
  2. JSP内置对象-request
  3. 拍拍网t恤DIY效果
  4. size-t数据类型 ssize-t数据类型
  5. 开源 java CMS - FreeCMS2.3会员个人资料
  6. vs2015 单元测试 linux,VS2015做单元测试
  7. .Net应用之数据连接(少儿助学网MisDataSet.dll)原代码
  8. mac下Python2运行SparkSQL
  9. Rust: Rangechar 'a'..'z' 能干什么?......待续
  10. qpython 3h下载_QPython 3Hv3.0.0 Android
  11. 程序员也要学英语——限定词、形容词和副词
  12. SNF开发平台-SNF.CodeGenerator-升级生成BS页面代码-支持视图-数据库配置-快速开发者的利器...
  13. 台式计算机没有声音,我们家台式电脑没有声音,该怎样设置
  14. 促进企业流量高质量转化,华为云CDN加速方案值得选择
  15. VS Code 高效“摸鱼”插件推荐
  16. ddt数据驱动 python接口 xls_013 python接口 数据驱动ddt
  17. leetcode_54. 螺旋矩阵
  18. YCM错误:“The ycmd server SHUT DOWN (restart with :YcmRestartServer)“
  19. Android WIFI架构
  20. 圆锥形SiC纳米磨削单晶硅源代码

热门文章

  1. 如何在IIS上配置多个网站,及网站发布配置讲解
  2. C#常用42个操作类
  3. CSS 类选择器详解——CSS 多类选择器
  4. 给DataList分页有两个办法:1、自定义实现分页方法 2、用第三方控件(例如AspNetPager)
  5. ASP.NET企业开发框架IsLine FrameWork系列之八--AppLogProvider日志框架(下)
  6. 漫步最优化三十九——Fletcher-Reeves法
  7. leetcode —— 98. 验证二叉搜索树
  8. Math3中StatUtils类和MathArrays的使用(数组运算)
  9. RANSAC估计——以直线拟合为例
  10. GOF之创建型模式(重点)