socket套接字
时间:2022-08-05
本文章向大家介绍socket套接字,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
传输层
TCP协议
1.TCP也就是传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,用于规定数据传输所遵循的规则
2.三次握手
2.1客户端发送SYN报文给服务器端,进入SYN_SEND状态
2.2服务器端收到SYN报文,回应一个SYN、ACK报文,进入SYN_RECV状态
2.3客户端收到服务器端的SYN报文,回应一个ACK报文,进入Established状态
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了
3.四次握手
3.1某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕
3.2接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认
3.3一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN
3.4接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN
既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节
'''
基于TCP传输数据非常的安全,不容易丢失,因为TCP有二次确认机制,每次发送数据后都需要返回确认消息,否则就会在一定的时间内反复发送
'''
UDP协议
1.UDP也就是用户数据报协议(User Datagram Protocol),UDP是支持一个无连接的传输协议,为应用程序提供了一种无需建立连接就可以发送封装的IP数据包的方法
2.UDP协议并不提供数据传送的保证机制,如果在从发送方到接收方的传递过程中出现数据包的丢失,协议本身并不能做出任何检测或提示,因此,通常人们把UDP协议称为不可靠的传输协议
'''
TCP:数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息
发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止
UDP:如果在从发送方到接收方的传递过程中出现数据包的丢失,协议本身并不能做出任何检测或提示
'''
应用层
主要取决于程序员自己采用什么策略和协议
常见协议有:HTTP HTTPS FTP...
socket套接字
套接字使用
1.基于文件类型的套接字家族的名字:AF_UNIX
2.基于网络类型的套接字家族的名字:AF_INET
'运行程序的时候,肯定是先运行服务端,之后才运行客户端'
服务端
import socket
# 1.创建一个socket对象
server = socket.socket() # 括号内什么都不写 默认就是基于网络的TCP套接字
# 2.绑定一个固定的地址(ip\port)
server.bind(('127.0.0.1', 8080)) # 127.0.0.1本地回环地址(只允许自己的机器访问)
# 3.半连接池
server.listen(5)
# 4.等待客户端连接
sock, address = server.accept() # sock是双向通道 address是客户端地址
# 5.数据交互
sock.send(b'hello') # 朝客户端发送数据
data = sock.recv(1024) # 接收客户端发送的数据 1024bytes
print(data)
# b'get out'
sock.close() # 断链接
server.close() # 关机
客户端
import socket
# 1.产生一个socket对象
client = socket.socket()
# 2.连接服务端(拼接服务端的ip和port)
client.connect(('127.0.0.1', 8080))
# 3.数据交互
data = client.recv(1024) # 接收服务端发送的数据
print(data)
# b'hello'
client.send(b'get out') # 朝服务端发送数据
client.close()
# 4.关闭
代码优化
1.send与recv
客户端与服务端不能同时执行收、同时执行发,有一个发,另一个就是收
2.消息自定义
使用(input)获取用户数据即可
3.循环通信
给数据交互环节添加循环(while)即可
4.服务端能够持续提供服务,不会因为客户端断开连接而报错
异常捕获,一旦客户端断开连接,服务端结束通信循环,调到连接处等待
5.消息不能为空
判断是否为空,如果是则重新输入(主要针对客户端)
6.服务端频繁重启可能会报端口被占用的错(主要针对mac电脑)
from socket import SOL_SOCKET,SO_REUSEADDR
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
7.客户端异常退出会发送空消息(针对mac linux)
针对接收的消息加判断处理即可
服务端
import socket
while True:
# 1.创建一个socket对象
server = socket.socket() # 括号内什么都不写 默认就是基于网络的TCP套接字
# 2.绑定一个固定的地址(ip\port)
server.bind(('127.0.0.1', 8080)) # 127.0.0.1本地回环地址(只允许自己的机器访问)
# 3.半连接池
try:
server.listen(5)
# 4.等待客户端连接
sock, address = server.accept() # sock是双向通道 address是客户端地址
# 5.数据交互
res = input('输入内容>>>:').strip()
if len(res) == 0:
res = '点错了,没消息'
sock.send(res.encode('utf8')) # 朝客户端发送数据
data = sock.recv(1024) # 接收客户端发送的数据 1024bytes
print(data.decode('utf8'))
except:
continue
客户端
import socket
while True:
# 1.产生一个socket对象
client = socket.socket()
# 2.连接服务端(拼接服务端的ip和port)
client.connect(('127.0.0.1', 8080))
# 3.数据交互
data = client.recv(1024) # 接收服务端发送的数据
print(data.decode('utf8'))
# b'hello'
res = input('输入内容>>>:').strip()
if len(res) == 0:
res = '点错了,没消息'
client.send(res.encode('utf8')) # 朝客户端发送数据
半连接池
server.listen(5)
主要是为了做缓冲,避免太多无效等待
黏包问题
1.黏包问题
所谓粘包就是连续给对端发送两个或者两个以上的数据包,对端在一次收取中收到的数据包数量可能大于 1 个,当大于 1 个时,可能是几个包加上某个包的部分,或者干脆就是几个完整的包在一起。当然,也可能收到的数据只是一个包的部分,这种情况一般也叫半包
2.TCP特性
流式协议:即协议的内容是像流水一样的字节流,内容与内容之间没有明确的分界标志,需要我们人为地去给这些协议划分边界
3.struct模块
import struct
info = '我现在内心感到悲痛欲绝 而且这份悲痛正渐渐转变为杀意'
print(len(info)) # 数据原本的长度
# 26
res = struct.pack('i', len(info)) # 将数据原本的长度打包
print(len(res)) # 打包之后的长度是4
# 4
ret = struct.unpack('i', res) # 将打包之后固定长度为4的数据拆包
print(ret[0]) # 又得到了原本数据的长度
# 26
'''
无论数据长度是多少,struct模块都可以打包成固定长度,然后基于固定长度,还可以反向解析出真实长度
1.将数据原本的长度打包成固定长度4
2.再根据报头解压出真实长度
3.根据真实长度接收即可
'''
原文地址:https://www.cnblogs.com/riuqi/p/16555669.html
- 图解闭包
- 【web必知必会】——图解HTTP(上)
- 【web必知必会】—— 图解HTTP(下)
- 【Spring实战】—— 14 传统的JDBC实现的DAO插入和读取
- 【AngularJS】—— 4 表达式
- 【AngularJS】—— 5 表单
- 【AngularJS】—— 1 初识AngularJs
- 【AngularJS】—— 2 初识AngularJs(续)
- 【AngularJS】—— 3 我的第一个AngularJS小程序
- 【Spring实战】—— 2 构造注入
- 共享单车运维“朋友圈”越来越宽,乱停乱放现象有望改善吗?
- 【Spring实战】—— 15 Spring JDBC模板使用
- 前端开发总览
- 【Spring实战】—— 16 基于JDBC持久化的事务管理
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 用工厂模式管理以太坊的多个solidity智能合约
- solidity语言开发以太坊智能合约中的继承
- Elasticsearch 最佳实践系列之分片恢复并发故障
- EOS智能合约开发和测试框架EOSFactory
- hadoop2-HBase的Java API操作
- ROS_机器人仿真实践
- React-Native开发笔记 持续更新
- 【长期维护】WordPress 基于腾讯云对象存储 COS 远程附件支持插件
- 常用的大数据技术有哪些?
- 使用CentOS 7.5卸载自带jdk安装自己的JDK1.8
- Elasticsearch API简单使用
- SDK集成第三方依赖发布Maven的方法
- 头条秋招面试题以及答案
- 聊聊storm tuple的序列化
- 聊聊storm TridentTopology的构建