网络编程tcp协议与socket以及单例的补充

一、单例补充

  • 实现单列的几种方式
#方式一:classmethod

# class Singleton:
#
# __instance = None
#
# @classmethod
# def singleton(cls):
#
# if not cls.__instance:
# cls.__instance = cls()
#
# return cls.__instance
#
# obj1 = Singleton.singleton()
# obj2 = Singleton.singleton()
# print(obj1)
# print(obj2)
# <__main__.Singleton object at 0x000002127F230D08>
# <__main__.Singleton object at 0x000002127F230D08> #方式二: __new__
# class Singleton:
#
# __instance = None
#
# def __new__(cls, *args, **kwargs):
#
# if not cls.__instance:
# cls.__instance = object.__new__(cls)
#
# return cls.__instance
#
# obj1 = Singleton()
# obj2 = Singleton()
# print(obj1)
# print(obj2)
# <__main__.Singleton object at 0x00000257AAE10A88>
# <__main__.Singleton object at 0x00000257AAE10A88> #方式三:装饰器
# def singleton(cls): #cls---> Father
#
# __instance = {}
#
# def inner(*args, **kwargs):
# if cls not in __instance:
# obj = cls(*args, **kwargs)
# __instance[cls] = obj
#
#
# return __instance[cls]
# return inner
#
# @singleton
# class Father:
# pass
#
# print(Father())
# print(Father())
# <__main__.Father object at 0x000001F17EB21548>
# <__main__.Father object at 0x000001F17EB21548> #方式四
先定义一个Singletoncls的py文件内容如下:
class Singletoncls:
pass obj = Singletoncls()
# from Singletoncls import obj
# print(obj)
# from Singletoncls import obj
# print(obj)
# from Singletoncls import obj
# print(obj)
# <Singletoncls.Singletoncls object at 0x00000249CD25BE48>
# <Singletoncls.Singletoncls object at 0x00000249CD25BE48>
# <Singletoncls.Singletoncls object at 0x00000249CD25BE48> # 方式五:元类

二、tcp协议以及粘包问题

  • 理论知识
传输层:
-tcp协议
-udp协议
端口(port):标识一台计算机上的某一个软件。
-0-1024:禁止使用,因为是操作系统在用
-8000---->以后接着用 - 以下的一些软件的固定端口不要碰:
django:8000
mysql:3306
redis:6379
flask:5000
tomcat:8080
mongodb:27017
...
要想要传输数据,必须建立双向通道 1、tcp协议:三次握手,四次挥手
-tcp协议建立双向通道 - 三次握手,键连接:
1:客户端向服务端发送建立连接的请求
2:服务端返回收到的请求信息给客户端,并且发送往客户端建立的请求
3:客户端接收到服务端的请求,返回请求成功给服务端,完成双向连接 - 反馈机制:
客户端往服务端发送请求,服务端必须返回响应
告诉客户端收到请求了,并且将服务端的数据一并返回给客户端
c--->s:一次请求,必须有一次响应 - 缺点:
- 洪水攻击:
指的是通过伪造大量的请求,往对方服务器发送请求
导致对方服务器跟不上,以至于瘫痪。
Linux系统有个参数可以限制 - 半连接池listen:限制用户在同一时间段内的访问数量 - 四次挥手,断开连接
1:客户端向服务端发送断开连接的请求
2:服务端返回收到请求的信息给客户端
3:服务端确认所有的数据发送完成以后,再发送同意断开连接的请求给客户端
4:客户端返回收到断开连接的请求,给服务端 2、socket套接字通信:
- 什么是socket?
socket是一个模块,又称套接字,用来封装 互联网协议(应用层以下的层) - 为什么要有socket?
socket可以实现 互联网协议应用层已下的层的工作
- 提高开发效率 - 怎么使用socket?
import socket
写socket套接字:
client
sever 3、粘包问题
-1)问题:无法确认对方发送过来的数据的大小 -2)问题:在发送数据间隔短并且数据量小的情况下,会将所有数据一次性发送 解决:确认对方数据的大小 4、解决粘包问题(struct模块)
-无论那一段发送数据
-客户端
-1)先制作报头,并发送(struct)
-2)发送真实数据 服务端
-1)接收报头,并解包获取 真实的数据长度
-2)根据真实数据长度 接收真实数据
recv(真实数据长度)

三、socket套接字

  • socket套接字初级版本
  • 演示
-sever:

'''
先启动套接服务端
''' import socket #买手机
sever = socket.socket() #绑定手机卡
sever.bind(
('127.0.0.1', 9876)
) #半连接池
sever.listen(5) #最多同时五个人坐椅子,实际上==6 print(
'服务端正在运行...'
) #等待电话接入
#coon:指的是服务端往客户端的管道
coon, addr = sever.accept() #接听对方讲话的内容
#data客户端发送过来的消息
data = coon.recv(1024) #一次性可接受1024bytes的数据
print(data) >>>服务端正在运行...
>>>b'hello' #挂电话
coon.close() -client:
'''
先启动服务端后再启动客户端
''' import socket #买手机
client = socket.socket() #拨打电话
client.connect(
('127.0.0.1', 9876)
) print('客户端正在运行...') #必须发送bytes类型的数据
#开始讲话
client.send(b'hello')
# 或client.send('hello'.encode('utf_8'))
>>>客户端正在运行...
  • socket套接字升级版本
- sever

'''
注意:
客户端法送一次,我服务端就得先接受一次,之后才可以再向客户端发送消息
''' import socket #买手机
sever = socket.socket() #绑定手机卡
#里面绑定的是一个元祖
sever.bind(
('127.0.0.1', 9876)
) #半连接池
sever.listen(5) print('服务端正在等待服务...') #等待电话接入
#coon:指的是服务端往客户端的管道 coon, addr = sever.accept() #接听对方讲话的内容
data = coon.recv(1024)
print(data) #服务端往客户端发送消息
coon.send(b'hi i am sever') #挂电话
coon.close() >>>服务端正在等待服务...
>>>b'hello i am client...' - client
'''
启动服务端后再启动客户端
'''
import socket #买手机
client = socket.socket() #拨号
client.connect(
('127.0.0.1', 9876)
) print('客户端正在发送请求...') client.send(b'hello i am client...') #接收服务端的请求
data = client.recv(1024) print(data) client.close()
>>>客户端正在发送请求...
>>>b'hi i am sever'
  • socket套接字高级版本
-sever

import socket

#买手机
sever = socket.socket() #绑定手机卡
sever.bind(
('127.0.0.1', 9876)
) #半连接池
sever.listen(5) print('服务端正在运行...') #等待电话接入
coon, addr = sever.accept() while True:
#接收对方讲话内容
#data客户端发送过来的消息
data = coon.recv(1024)
if len(data) == 0:
break
if data.decode('utf-8') == 'q':
break
print(data.decode('utf-8')) send_data = input('服务端...') coon.send(send_data.encode('utf-8')) #挂电话
coon.close()
服务端正在运行...
服务端...你好啊亚峰 -client import socket #买手机
client = socket.socket() #拨打电话
client.connect(
('127.0.0.1', 9876)
) print('客户端正在发送请求...') while True:
send_data = input('客户端>>>:').strip()
client.send(send_data.encode('utf-8'))
data = client.recv(1024)
if data.decode('utf-8') == 'q':
break
if len(data) == 0:
break print(data.decode('utf-8')) client.close()
>>>客户端正在发送请求...
>>>客户端>>>:你好啊热巴
>>>好啊亚峰
  • socket套接字终级版本
- sever

import socket

#买手机
sever = socket.socket() #绑定手机卡
sever.bind(
('127.0.0.1', 9876)
) #半连接池
sever.listen(5) print('服务端正在服务...') #循环实现可接受多个用户访问
while True: coon, addr = sever.accept()
print(addr) #循环实现通信
while True:
try:
#监听代码是否有异常出现
#接听对方讲话的内容
#data客户端发送过来的消息
data = coon.recv(1024) if len(data) == 0:
break if data.decode('utf-8') =='q':
break print(data.decode('utf-8')) send_data = input('服务端>>>...') #服务端向客户端发送消息
coon.send(send_data.encode('utf-8')) except Exception as e:
print(e)
break #挂电话
coon.close() >>>
服务端正在服务...
('127.0.0.1', 52467)
我想找迪丽热巴
服务端>>>...你好啊亚峰,我是热巴,有什么能帮你吗
热巴youare beautiful
服务端>>>...谢谢亚峰 -client import socket #买手机 client = socket.socket() #拨打号码
client.connect(
('127.0.0.1', 9876)
) print('客户端正在发送请求...') while True:
send_data = input('客户端>>>:')
client.send(send_data.encode('utf-8'))
data = client.recv(1024) if data.decode('utf-8') == 'q':
break if len(data) == 0:
break print(data.decode('utf-8'))
>>>
client.close()
客户端正在发送请求...
客户端>>>:我想找热巴
你好啊亚峰,我是热巴,有什么能帮你吗
客户端>>>:热巴you are beautiful
谢谢亚峰
客户端>>>:

四、粘包问题

  • 粘包问题的出现以及几种情况
  • 第一个问题
-sever
#问题一不知道数据的具体长度
# import socket
#
# import subprocess
#
# #买手机
# sever = socket.socket()
#
# #绑定电话卡
# sever.bind(
# ('127.0.0.1', 9867)
# )
#
# #半整数池
# sever.listen(5)
#
# while True:
# coon, addr = sever.accept()
# print(addr)
#
# while True:
# try:
# #recv从内存中获取数据
# cmd = coon.recv(1024)
#
# if len(cmd) == 0:
# continue
# cmd = cmd.decode('utf-8')
# if cmd == 'q':
# break
#
# #调用subprocess连接终端,对终端进行操作,并获取操作后正确或错误的结果
# obj = subprocess.Popen(
# cmd, shell=True, stdout=subprocess.PIPE,
# stderr=subprocess.PIPE
# )
# #结果交给result变量名
# result = obj.stdout.read() + obj.stderr.read()
# print(len(result))
#
# #windows默认是gbk
# print(result.decode('gbk'))
#
# #将结果返回给客户端
# coon.send(result)
# except Exception as e:
# print(e)
# break
#
# coon.close() -client
# import socket
#
# client = socket.socket()
#
# client.connect(
# ('127.0.0.1', 9867)
# )
#
# while True:
#
# cmd = input('客户端输入的内容:')
#
# client.send(cmd.encode('utf-8'))
#
# data = client.recv(19190)
#
# print(len(data))
#
# print(data.decode('gbk'))
  • 第二种问题
-sever

#问题二:当发送多次传入的数据长度却不是很长的时候,服务端多次接收后面接收的没内容

import socket

sever = socket.socket()

sever.bind(
('127.0.0.1', 9000)
) sever.listen(5) coon, addr = sever.accept() data = coon.recv(10)
print(data) data = coon.recv(1024)
print(data) data = coon.recv(1024)
print(data)
>>>b'hellohello'
>>>b'hello'
>>>b'' - client
#问题二
import socket client = socket.socket() client.connect(
('127.0.0.1', 9000)
) client.send(b'hello')
client.send(b'hello')
client.send(b'hello')

五、解决粘包问题

  • 演示
- sever

import socket
import subprocess
import struct sever = socket.socket() sever.bind(
('127.0.0.1', 9000)
) sever.listen(5) while True:
coon, addr = sever.accept()
print(addr) while True:
try: #获取客户端传过来的报头
header = coon.recv(4) #解包获取真实的数据长度
data_len = struct.unpack('i', header)[0] #准备接收真实数据
cmd = coon.recv(data_len) if len(cmd) == 0:
continue cmd = cmd.decode('utf-8') if cmd == 'q':
break #调用subprocess连接终端,对终端进行操作,并获取操作后的正确或错误的结果
obj = subprocess.Popen(
cmd, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
) #结果交给result变量名
result = obj.stdout.read() + obj.stderr.read() print('发送给客户端的真实长度', len(result)) #将结果返回给客户端,做一个报头,返回给客户端
header = struct.pack('i', len(result))
print(len(header))
coon.send(header)
coon.send(result) except Exception as e:
print(e)
break coon.close() - client import struct
import socket client = socket.socket() client.connect(
('127.0.0.1', 9000)
) while True: cmd = input('客户端输入的内容:') cmd_bytes = cmd.encode('utf-8') #做一个报头
header = struct.pack('i', len(cmd_bytes)) print(len(header)) client.send(header) #待服务器确认长度以后,再发送真实数据长度
client.send(cmd_bytes) #接收服务端返回的报头
s_header = client.recv(4) #解包,接收服务端返回的真实数据
data_len = struct.unpack('i', s_header)[0] result = client.recv(data_len) print('接收服务器返回的真实数据长度', len(result))
print(result.decode('gbk'))
  • 演示二
-sever

import socket
import struct
import json sever = socket.socket() sever.bind(
('127.0.0.1', 9000)
) sever.listen(5) while True: coon, addr = sever.accept()
print(addr) while True:
try:
#获取客户端传来的报头
header = coon.recv(4) #解包,获取真实的数据长度
json_len = struct.unpack('i', header)[0] #接收json(dictionary)的真实长度
json_bytes_data = coon.recv(json_len) #反序列化将bytes类型数据变成json数据
json_data = json_bytes_data.decode('utf-8') back_dic = json.loads(json_data)
print(back_dic)
print(back_dic.get('movie_len')) except Exception as e:
print(e)
break coon.close() >>>('127.0.0.1', 53414)
>>>{'movie_name': '色戒', 'movie_len': 100000}
>>>100000 -client
import struct
import socket
import json client = socket.socket() client.connect(
('127.0.0.1', 9000)
) while True: movie_name = input('请输入上传电影的名字:').strip() #伪装电影真实数据
movie_len = 100000 send_dic = {
'movie_name': movie_name,
'movie_len': movie_len
} #序列化
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', len(json_bytes)) #发送报头
client.send(header) #发送真实数据
client.send(json_bytes) >>>请输入上传电影的名字:色戒

网络编程之tcp协议以及粘包问题的更多相关文章

  1. day28 8_7 网络编程之tcp协议

    一.socket模块 socket模块就是用来网络搭建的模块,socket也叫套接字. 创建网络连接,需要使用两个模块进行模拟,一个作为server服务器端,一个作为client客户端. 在服务器端, ...

  2. 网络编程之TCP协议与UDP协议

    了解网络就要了解一些基本的协议今天主要跟大家分享一些关于TCP 协议UDP协议的相关知识 首先介绍一下TCP协议 TCP(Transmission Cintrol Protocol)可靠的.面向连接的 ...

  3. 网络编程之TCP协议怎么使用?

    TCP 通信的客户端:向服务器发送连接请求,给服务器发送数据,读取服务器会写的数据 表示客户端的类: java.net.Socket;此类实现客户端套接字.套接字是两台机器间通信的端点 套接字:包含了 ...

  4. java 26 - 7 网络编程之 TCP协议代码优化

    上次所写的代码中,客户端和服务器端所进行的数据传输所用的是字节流. 优化: A:这次,为了高效,对这个字节流通过转换流来进行包装,包装成高效字符流. B:这次,传输的数据是通过键盘录入的数据. 服务器 ...

  5. java 26 - 6 网络编程之 TCP协议 传输思路 以及 代码

    TCP传输 Socket和ServerSocket 建立客户端和服务器 建立连接后,通过Socket中的IO流进行数据的传输 关闭socket 同样,客户端与服务器是两个独立的应用程序 TCP协议发送 ...

  6. python六十九课——网络编程之TCP协议

    1.1 概述: TCP协议通过三次握手协议将客户端与服务器端连接,两端使用各自的Socket对象.Socket对象中包含了IO流,供数据传输. 即:TCP协议在客户端与服务器端通过Socket组成了I ...

  7. java 26 - 9 网络编程之 TCP协议多用户上传文件

    TCP实现多用户上传文件: 需要同时给多用户上传文件,这样就得用多线程来实现. 实际上,这样的话,上传的先后顺序和速度就跟客户端的带宽有关:带宽够,就容易抢占到线程的执行权: 首先,创建个线程类:(这 ...

  8. java 26 - 8 网络编程之 TCP协议的练习

    TCP练习: 1.客户端键盘录入,服务器输出文本文件 客户端代码: public class ClientDemo { public static void main(String[] args) t ...

  9. java 26 - 8 网络编程之 TCP协议上传图片

    上次的是上传TXT文件,这次上传的是图片.同样,上传成功需要反馈给客户端. 区别: TXT文件用记事本打开,我们可以看得懂,所以用了缓冲字符流,对通道内的字节流进行包装了. 而图片用记事本打开,我们看 ...

随机推荐

  1. Spring注解之@Autowired

    前言 说起Spring的@Autowired注解,想必大家已经熟悉的不能再熟悉了.本文就针对此最常用的注解,梳理一下它的功能和原理,争取从源码的角度将此注解讲通,如有写的不准确的地方,欢迎各位园友拍砖 ...

  2. Prometheus学习系列(九)之Prometheus 联盟、迁移

    前言 本文来自Prometheus官网手册 和 Prometheus简介 FEDERATION 允许Prometheus服务器从另一台Prometheus服务器抓取选定的时间序列. 一,用例 联盟有不 ...

  3. Audit Object Changes 审核对象更改

    Important 重要 The Audit Trail module is not supported by the Entity Framework ORM in the current vers ...

  4. vs2017 输出 ling to sql 转为执行的sql语句

    在项目视图中,找到->输出 窗口,在窗口中选择ASP.NET Core Web服务器,调试项目即可看到执行的sql语句

  5. 配置基于服务器认证的Dynamics 365 Customer Engagement和SharePoint Online集成

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  6. 斐波那契数列(Java)

    一.什么是斐波那契数列 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为& ...

  7. android 启动流程 相关 杂项记录

    Android原生流程 Init进程 主要流程及分支梳理 ueventd_main()watchdogd_main()主要流程a) 公共部分 增加PATH 环境变量初始化内核日志,打开/dev/kms ...

  8. JavaScript-----11.预解析

    1.预解析 1.1引子 //1问 console.log(num);//报错 num未定义 //2问 console.log(num); //undefined 未报错 var num = 10; / ...

  9. 11. Go 语言网络编程

    Go 语言网络编程 Go语言在编写 web 应用方面非常得力.因为目前它还没有 GUI(Graphic User Interface 图形化用户界面)的框架,通过文本或者模板展现的 html 界面是目 ...

  10. 【第二章】Zabbix3.4监控SQLServer数据库和H3C交换机思科Cisco防火墙交换机教程笔记

    监控SQLServer数据库 SSMS执行相关SQL SQL模板命名规则 Zabbix客户端导入模板 添加SQLServer监控图形 SQLServer服务器关联模板 监控思科Cisco防火墙交换机 ...