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套接字(完全版)的更多相关文章

  1. 网络编程基础之Socket套接字简单应用

    一.Socket套接字实现通信循环 所谓通信循环,简单理解就是客户端可以给服务端循环发送信息并获得反馈的过程. 1.基础版 通信循环的程序分为两部分,即两个python模块,分别为客户端.py和服务端 ...

  2. 8.7 day28 网络编程 socket套接字 半连接池 通信循环 粘包问题 struct模块

    前置知识:不同计算机程序之间的数据传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...

  3. 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

    TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...

  4. Python socket套接字通信

    一.什么是socket? socket是一个模块, 又称套接字,用来封装 互联网协议(应用层以下的层). 二.为什么要有socket? socket可以实现互联网协议 应用层以下的层 的工作,提高开发 ...

  5. 网络编程与socket套接字

    网络编程与socket套接字 传输层 PORT协议 port是一种接口,数据通过它在计算机和其他设备(比如打印机,鼠标,键盘或监视器)之间,网络之间和其他直接连接的计算机之间传递 TCP协议 ​ 传输 ...

  6. java 25 - 3 网络编程之 Socket套接字

    Socket Socket套接字: 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字. Socket原理机制: 通信的两端都有Socket. 网络通信其实就是Socket ...

  7. 进程、线程、socket套接字-资源大小 & 切换代价

    另,进程 & 线程的很多知识可以看这里:http://www.cnblogs.com/charlesblc/p/6135666.html 今天查了一下进程和线程的资源占用. 比如问:栈和堆的大 ...

  8. linux网络环境下socket套接字编程(UDP文件传输)

    今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...

  9. linux网络编程-(socket套接字编程UDP传输)

    今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...

随机推荐

  1. Mybatis02

    1.mybatis动态sql   foreach 添加接口方法 编写BookVo类 BookMapper.xml 测试 结果 2.模糊查询 3.查询返回结果集 resultMap:适合使用返回值是自定 ...

  2. 在触发器中使用{ITEM.LASTVALUE}时在首页问题栏信息显示不全

    在触发器中使用了系统宏变量,当条件满足时,如果这个宏代表的内容超过了20个字符,那么在首页信息就显示不全,会有一堆省略号 感谢https://blog.csdn.net/yu415907917/art ...

  3. python内置模块2

    十五.shutil模块 ==================================================================== shutil模块是python为我们封 ...

  4. 探索性数据分析(Exploratory Data Analysis,EDA)

    探索性数据分析(Exploratory Data Analysis,EDA)主要的工作是:对数据进行清洗,对数据进行描述(描述统计量,图表),查看数据的分布,比较数据之间的关系,培养对数据的直觉,对数 ...

  5. TEX Quotes

    题目链接:https://cn.vjudge.net/problem/UVA-272 AC代码: /* */ #include <iostream> #include <stdio. ...

  6. php 进制转换base_convert

    16进制 转为 8进制 base_convert(number,frombase,tobase); 参数 描述 number 必需.规定要转换的数. frombase 必需.规定数字原来的进制.介于 ...

  7. pycharm无法识别自己的文件夹的程序

    网上找教程折腾了半天也没解决,然后我换了一下文件夹名称…… 文件夹名称不能用数字开头,否则识别不出来.

  8. 牛顿插值法(c++)【转载】

    摘自<c++和面向对象数值计算>,代码简洁明快,采用模板函数,通用性增强,牛顿差分合理利用存储空间,采用Horner算法(又称秦九韶算法)提高精度,减少时间复杂度,高!确实是高!对其中代码 ...

  9. 通过sed -i ,通过准备好的sh脚本,来设置linux iptable白名单

    通过准备好的sh脚本,来设置linux iptable白名单 特定字符串的行前插入新行 sed -i '/特定字符串/i 新行字符串' file #!/bin/bash del_stdin_buf() ...

  10. Freemarke

    本文介绍了freemarker的集成.FTL指令.内建函数.运算符等常用操作. 1.为什么要使用网页静态化技术 网页静态化解决方案在实际开发中运用比较多,例如新闻网站,门户网站中的新闻频道或者是文章类 ...