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的传输协议来进行传输,但是在文件的传输中, ...
随机推荐
- BZOJ 3689: 异或之 可持久化trie+堆
和超级钢琴几乎是同一道题吧... code: #include <bits/stdc++.h> #define N 200006 #define ll long long #define ...
- 2019.12.09 java for循环
for(初始化表达式; 循环条件; 操作表达式){ 执行语句 ……… } 先走初始化表达式,再走循环条件,如条件满足,走执行语句,然后走操作表达式,再走循环条件,如条件满足,走执行语句 ...
- idea 导入 eclipse java ee 项目,并使用 tomcat 7 部署运行
1.导入java ee项目.直接open 2.导入jar依赖 3.修改编译的目录 4.修改tomcat目录 5.tomcat添加目录 请注意classes单词 D:\project\xxxxxx\We ...
- 可持久化01trie树——模板
给你一个数,在一段区间内找到另一个数,使得他们的异或最大: trie树上存储每个数的二进制位,查询时贪心查询能让当前高位取得1的位置: 实际上是一个求前缀和的思想.每个数都开一个trie树浪费空间,当 ...
- 深度clone和浅clone
首先等你有空的时候可以看这篇,要用可以看我这篇 https://www.cnblogs.com/echolun/p/7889848.html 1.有一点需要明确的是 深拷贝只是针对引用数据类型来说的, ...
- [C++] namespace命名空间和using用法
命名空间namespace:指标识符的各种可见范围. C++标准程序库中的所有标识符都被定义在一个std的namespace,这就是程序开始添加 using namespace std; 的原因. 很 ...
- 一次解决idea maven settings.xml文件不生效
一直使用eclipse,在eclipse中可以手动指定global和user settings,并且settings的文件名称可以不是settings.xml,只要内容符合maven规范就行.如下: ...
- uniapp - 关于ios调试
[ios调试] 1.一台windows电脑.一根apple数据线(一旦连接以后,apple设备就会自动识别itunes软件,如果没有安装会提示) 2.安装itunes (爱思助手) 3.官方教程:ht ...
- 解决iis内存占用过大的问题--ZT
解决iis内存占用过大的问题 在IIS6下,经常出现w3wp的内存占用不能及时释放,从而导致服务器响应速度很慢. 今天研究了一下,可以做以下配置: 1.在IIS中对每个网站进行单独的应用程序池配置.即 ...
- python3新特性函数注释Function Annotations用法分析
本文分析了python3新特性函数注释Function Annotations用法.分享给大家供大家参考,具体如下: Python 3.X新增加了一个特性(Feature),叫作函数注释 Functi ...