day30——socket套接字(完全版)
day30
基于TCP协议的socket循环通信
server
import socket
phone = socket.socket()
phone.bind(("127.0.0.1", 8080))
phone.listen()
conn, addr = phone.accept()
from_client_data = conn.recv(1024)
print(f"来自客户端的消息:{from_client_data.decode('utf-8')}")
conn.close()
phone.close()
client
import socket
phone = socket.socket()
phone.connect(("127.0.0.1", 8080))
data = input("请输入>>>")
phone.send(data.encode("utf-8"))
phone.close()
基于TCP协议的socket 链接+循环 通信
代码功能:服务器不会断开,客户端可以断开(且不能输入空字符串)
server
import socket
phone = socket.socket()
phone.bind(("127.0.0.1", 8080))
phone.listen(3)
while 1:
conn, addr = phone.accept()
print(f"{addr}客户端连接了")
while 1:
try:
from_client_data = conn.recv(1024)
if from_client_data.decode("utf-8").upper() == "Q":
print(f"{addr}客户端通信关闭!")
break
else:
print(f"来自客户端的消息:{from_client_data.decode('utf-8')}")
while True:
data = input("请输入>>>")
if not data:
print("输入内容不为空!")
continue
else:
break
conn.send(data.encode("utf-8").upper())
except Exception:
print(f"{addr}客户端通信关闭!")
break
conn.close()
phone.close()
clicent
import socket
phone = socket.socket()
phone.connect(("127.0.0.1", 8080))
while 1:
try:
data = input("请输入>>>")
if not data:
print("输入内容不为空!")
continue
phone.send(data.encode("utf-8"))
if data.upper() == "Q":
print("通信关闭!")
break
from_server_data = phone.recv(1024)
if from_server_data.decode("utf-8").upper() == "Q":
print("通信关闭!")
break
else:
print(f"来自服务器的消息:{from_server_data.decode('utf-8')}")
except Exception:
print("通信关闭!")
break
phone.close()
基于TCP协议的socket通信:实例:远程执行命令
bates:网络传输,文件存储时
server
import socket
phone = socket.socket()
phone.bind(("127.0.0.1", 8080))
phone.listen(3)
while 1:
conn, addr = phone.accept()
print(f"{addr}客户端连接了")
while 1:
try:
from_client_data = conn.recv(1024)
import subprocess
obj = subprocess.Popen(from_client_data.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
conn.send((obj.stdout.read() + obj.stderr.read()).upper())
except Exception:
print(f"{addr}客户端通信关闭!")
break
conn.close()
phone.close()
client
import socket
phone = socket.socket()
phone.connect(("127.0.0.1", 8080))
while 1:
try:
data = input("请输入>>>")
if not data:
print("输入内容不为空!")
continue
phone.send(data.encode("utf-8"))
if data.upper() == "Q":
print("通信关闭!")
break
from_server_data = phone.recv(1024)
print(from_server_data.decode('gbk'))
except Exception:
print("通信关闭!")
break
phone.close()
粘包现象
为什么出现粘包?

只有TCP有粘包现象,UDP永远不会粘包!
操作系统的缓冲区
- 为什么存在缓冲区
- 暂时存储一些数据
- 缓冲区存在如果你的网络波动,保证数据的收发稳定,匀速
缺点:造成了粘包现象之一
什么情况下出现粘包?
出现粘包的情况
- 客户端发送了一段数据过大,服务端只收了一部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包
server
# import socket
# import subprocess
# phone = socket.socket()
# phone.bind(('127.0.0.1',8848))
# phone.listen(2)
# # listen: 2 允许有两个客户端加到半链接池,超过两个则会报错 # while 1:
# conn,addr = phone.accept() # 等待客户端链接我,阻塞状态中
# # print(f'链接来了: {conn,addr}')
# while 1:
# try:
# from_client_data = conn.recv(1024) # 最多接受1024字节
# if from_client_data.upper() == b'Q':
# print('客户端正常退出聊天了')
# break
# obj = subprocess.Popen(from_client_data.decode('utf-8'),
# shell=True,
# stdout=subprocess.PIPE,
# stderr=subprocess.PIPE,
# )
# result = obj.stdout.read() + obj.stderr.read()
# print(f'总字节数:{len(result)}')
# conn.send(result)
# except ConnectionResetError:
# print('客户端链接中断了')
# break
# conn.close()
# phone.close()
client
# import socket
#
# phone = socket.socket()
#
# phone.connect(('127.0.0.1',8848))
# while 1: # to_server_data = input('>>>输入q或者Q退出').strip().encode('utf-8') # if not to_server_data: # # 服务端如果接受到了空的内容,服务端就会一直阻塞中,所以无论哪一端发送内容时,都不能为空发送 # print('发送内容不能为空') # continue # phone.send(to_server_data) # if to_server_data.upper() == b'Q': # break # from_server_data = phone.recv(300) # 最多接受1024字节 # # print(f'{from_server_data.decode("gbk")}') # print(len(from_server_data)) # phone.close()
- 连续短暂的send多次(数据量很小),你的数据会统一发送出去
server
2. 连续短暂的send多次(数据量很小),你的数据会统一发送出去.
# import socket
# phone = socket.socket()
#
# phone.bind(('127.0.0.1',8848))
#
# phone.listen(5)
#
#
# conn,addr = phone.accept() # 等待客户端链接我,阻塞状态中
#
# from_client_data = conn.recv(1024) # 最多接受1024字节
# print(f'来自客户端{addr}消息:{from_client_data.decode("utf-8")}')
# conn.close()
# phone.close()```python
client
```python
# 2. 连续短暂的send多次(数据量很小),你的数据会统一发送出去.
# import socket
#
# phone = socket.socket()
#
# phone.connect(('127.0.0.1',8848))
#
#
# phone.send(b'he')
# phone.send(b'll')
# phone.send(b'o')
#
#
# phone.close()
# Nigle算法
深入研究收发
不一定是一收一发
- 发多次收一次
server
# 发多次收一次
# import socket
# phone = socket.socket()
# phone.bind(('127.0.0.1',8848))
# phone.listen(5)
# conn,addr = phone.accept() # 等待客户端链接我,阻塞状态中
# from_client_data = conn.recv(1024) # 最多接受1024字节
# print(f'来自客户端{addr}消息:{from_client_data.decode("utf-8")}')
# conn.close()
# phone.close()
client
# 发多次收一次
import socket
phone = socket.socket()
phone.connect(('127.0.0.1',8848))
phone.send(b'he')
phone.send(b'llo')
phone.close()
Nigle算法
- 发一次收多次
server
# 发一次收多次
# import socket
# phone = socket.socket()
# phone.bind(('127.0.0.1',8848))
# phone.listen(5)
# conn,addr = phone.accept() # 等待客户端链接我,阻塞状态中
# from_client_data = conn.recv(3) # 最多接受1024字节
# print(f'来自客户端{addr}消息:{from_client_data.decode("utf-8")}')
# from_client_data = conn.recv(3) # 最多接受1024字节
# print(f'来自客户端{addr}消息:{from_client_data.decode("utf-8")}')
# from_client_data = conn.recv(3) # 最多接受1024字节
# print(f'来自客户端{addr}消息:{from_client_data.decode("utf-8")}')
# from_client_data = conn.recv(3) # 最多接受1024字节
# print(f'来自客户端{addr}消息:{from_client_data.decode("utf-8")}')
# conn.close()
# phone.close()
client
# 发一次收多次
# import socket
# phone = socket.socket()
# phone.connect(('127.0.0.1',8848))
# phone.send(b'hello world')
# phone.close()
如何解决粘包现象
解决粘包现象的思路:
服务端发一次数据 10000字节
客户端接收数据时,循环接收,每次(至多)接收1024个字节,直至将所有的字节全部接收完毕,将接收的数据拼接在一起,最后解码
遇到的问题1:recv的次数无法确定
你发送总具体数据之前,先给我发一个总数据长度:5000个字节,如何在发送总数居
客户端:先接收一个长度,5000个字节
然后我再循环recv 控制循环的条件就是只要你接收的数据< 5000 一直接收
遇到的问题2:总数据的长度转化成的字节数不固定
你要将total_size int类型转化成bytes类型才可以发送
387 ---- > str(387) '387' ---->bytes b'387' 长度 3bytes
4185 ----> str(4185) '4185' ---->bytes b'4185' 长度 4bytes
18000------------------------------------------------------> 长度 5bytes
我们要解决:
将不固定长度的int类型转化成固定长度的bytes并且还可以翻转回来
struct模块
服务端:
import struct
total_size = len(result)
print(f'总字节数:{total_size}')
head_bytes = struct.pack('i',total_size)
conn.send(head_bytes)
conn.send(result)
total_size int类型
客户端:
head_bytes = phone.recv(4)
total_size = struct.unpack('i',head_bytes)[0]

low版解决粘包现象
server
import socket
import subprocess
import struct
phone = socket.socket()
phone.bind(("127.0.0.1", 8080))
phone.listen(3)
while 1:
conn, addr = phone.accept()
print(f"{addr}客户端连接了")
while 1:
try:
from_client_data = conn.recv(1024)
obj = subprocess.Popen(from_client_data.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
data = obj.stdout.read() + obj.stderr.read()
data_len = len(data)
print(f"长度:{len(data)}")
conn.send(struct.pack("i", data_len))
conn.send(data)
except Exception:
print(f"{addr}客户端通信关闭!")
break
conn.close()
phone.close()
client
import socket
import struct
phone = socket.socket()
phone.connect(("127.0.0.1", 8080))
while 1:
data = input("请输入>>>")
if not data:
print("输入内容不为空!")
continue
phone.send(data.encode("utf-8"))
if data.upper() == "Q":
print("通信关闭!")
break
data_deposit = b""
data_head = phone.recv(4)
data_new = struct.unpack("i", data_head)[0]
while len(data_deposit) < data_new:
data_deposit += phone.recv(1024)
print(data_deposit.decode("gbk"))
phone.close()
day30——socket套接字(完全版)的更多相关文章
- 网络编程基础之Socket套接字简单应用
一.Socket套接字实现通信循环 所谓通信循环,简单理解就是客户端可以给服务端循环发送信息并获得反馈的过程. 1.基础版 通信循环的程序分为两部分,即两个python模块,分别为客户端.py和服务端 ...
- 8.7 day28 网络编程 socket套接字 半连接池 通信循环 粘包问题 struct模块
前置知识:不同计算机程序之间的数据传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...
- 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法
TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...
- Python socket套接字通信
一.什么是socket? socket是一个模块, 又称套接字,用来封装 互联网协议(应用层以下的层). 二.为什么要有socket? socket可以实现互联网协议 应用层以下的层 的工作,提高开发 ...
- 网络编程与socket套接字
网络编程与socket套接字 传输层 PORT协议 port是一种接口,数据通过它在计算机和其他设备(比如打印机,鼠标,键盘或监视器)之间,网络之间和其他直接连接的计算机之间传递 TCP协议 传输 ...
- java 25 - 3 网络编程之 Socket套接字
Socket Socket套接字: 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字. Socket原理机制: 通信的两端都有Socket. 网络通信其实就是Socket ...
- 进程、线程、socket套接字-资源大小 & 切换代价
另,进程 & 线程的很多知识可以看这里:http://www.cnblogs.com/charlesblc/p/6135666.html 今天查了一下进程和线程的资源占用. 比如问:栈和堆的大 ...
- linux网络环境下socket套接字编程(UDP文件传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
- linux网络编程-(socket套接字编程UDP传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
随机推荐
- Oracle 查看index是否失效
一.普通索引是否失效 select * from dba_indexes s where s.owner in ('ISMP','BOSS','PAY','ACCOUNT','SETTLE','TE ...
- MongoDB 4.2 新特性解读 (转载)
MongoDB World 2019 上发布新版本 MongoDB 4.2 Beta,包含多项数据库新特性,本文尝试从技术角度解读. Full Text Search MongoDB 4.2 之前,全 ...
- [HAOI2015]树上染色 树状背包 dp
#4033. [HAOI2015]树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的N-K个点染成白 ...
- 洛谷 题解 P2721 【摄像头】
这是我见过最水的蓝题 这不就是拓扑排序板子题吗 题目大意:松鼠砸烂摄像头不被抓住 摄像头一个可以监视到另一个可以看做有向边,用邻接链表储存就好了,我也不知道邻接矩阵到底能不能过保险起见还是用邻接链表. ...
- centos7中运行ifconfig提示-bash: ifconfig: command not found
centos7中运行ifconfig提示-bash: ifconfig: command not found 查看/sbin/下是否有ifconfig,若没有通过如下命令安装 sudo yum ins ...
- GDOI2018 小学生图论题 [NTT]
并没有传送门qwq 思路 首先要知道一个结论(或者说是一个套路):一个竞赛图缩点之后必定是一条链. 那么强联通分量的个数,就是这条链的边数+1. 考虑一条边什么时候会出现:当且仅当点集可以被分成\(S ...
- iphone中input按钮设置disabled属性出现灰色背景没有显示问题
在项目中发现发送验证码的按钮,在点击后添加disabled属性后,iphone手机中出现disabled属性的默认背景颜色没有显示,反而直接显示它下面的父级元素的白色 点击前 点击后 倒计时的按钮消失 ...
- 备份和还原 Linux 上的 SQL Server 数据库
备份数据库 在下面的示例sqlcmd连接到本地 SQL Server 实例,并采用完整备份的名为的用户数据库demodb. sqlcmd -S localhost -U SA -Q "BAC ...
- 帝国CMS万能标签标题截取后自动加入省略号
帝国CMS万能标签标题截取后自动加入省略号,没有达到字数的则不加省略号完美解决方案1.打开e/class/connect.php 搜索 if(!empty($subtitle))//截取字符 大约 ...
- Calcite分析 - Rule
Calcite源码分析,参考: http://matt33.com/2019/03/07/apache-calcite-process-flow/ https://matt33.com/2019/03 ...