day8 socket
代码:
例子1:socket tcp 通讯
server端
- import socket
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
print(conn)
print(addr)
from_client_msg = conn.recv(1024)
print(from_client_msg)
conn.send(b"Hello it's me")
conn.close()
server.close()
client端
- import socket
client = socket.socket()
client.connect(("127.0.0.1",8001))
client.send(b"Who are you")
from_server_msg = client.recv(1024)
print(from_server_msg)- 例子2:socket udp 通讯
- server端
- import socket
udp_server = socket.socket(type=socket.SOCK_DGRAM)
ip_port = ('127.0.0.1',8001)
udp_server.bind(ip_port)
msg,addr = udp_server.recvfrom(1024)
print("来自客户端消息:",msg)
udp_server.sendto(b'I am udpserver',addr)
udp_server.close()
- client端
- import socket
udp_client = socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ("127.0.0.1",8001)
udp_client.sendto(b"I am udpclient",server_ip_port)
print(udp_client)
from_server_msg = udp_client.recvfrom(1024)
print("来自服务端",from_server_msg)
udp_client.close()- 查看缓冲区大小
- import socket
server = socket.socket()- size = server.getsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF) ps:查看发送缓冲区大小
print(size)- size1 = server.getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF) ps:查看接收缓冲区大小
print(size1)
- 例子3:Tcp 服务端和客户端通信
服务端
- import socket
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
print(conn)
print(addr)
while 1:
from_client_msg = conn.recv(1024)
print("来自客户端的信息:", from_client_msg.decode("utf-8"))
server_msg = input("服务端说:")
conn.send(server_msg.encode("utf-8"))- conn.close()
server.close()- 客户端一号
- import socket
client_01 = socket.socket()
ip_port = ('127.0.0.1',8001)
client_01.connect(ip_port)
while 1:
client_msg = input("客户端一号说:")
client_01.send(client_msg.encode("utf-8"))
from_server_msg = client_01.recv(1024)
print(from_server_msg.decode("utf-8"))- 客户端2号
- import socket
clinet_02 = socket.socket()
ip_port = ("127.0.0.1",8001)
clinet_02.connect(ip_port)
while True:
clinet_02_msg = input("客户端2号说: ")
clinet_02.send(clinet_02_msg.encode("utf-8"))
from_server_msg = clinet_02.recv(1024)
print(from_server_msg.decode("utf-8"))
- ps:tcp一次只能连接一个client在这个例子里面
- 例子4:多个udp客户端和单个upd服务端通信
- 服务端
- import socket
server = socket.socket(type=socket.SOCK_DGRAM)
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)- while 1:
from_client_msg,addr = server.recvfrom(1024)
print("客户端说:",from_client_msg.decode("utf-8"))
server_msg = input("服务端说:")
server.sendto(server_msg.encode("utf-8"),addr)- 客户端01号说:
- import socket
client_01 = socket.socket(socket.AF_INET,type=socket.SOCK_DGRAM)
ip_port = ("127.0.0.1",8001)
while 1:
client_01_say = input("客户端一号说:")
client_01.sendto(client_01_say.encode("utf-8"),ip_port)
msg,addr = client_01.recvfrom(1024)
print("来自服务端的消息:",msg.decode("utf-8"),addr)- 客户端2号
- import socket
client_02 = socket.socket(type=socket.SOCK_DGRAM)
ip_port = ("127.0.0.1",8001)
while 1:
msg = input("客户端2号说:")
send_to_server = client_02.sendto(msg.encode("utf-8"),ip_port)
rev_from_server,addr = client_02.recvfrom(1024)
print(rev_from_server.decode("utf-8"))- ps:在这个例子中,upd客户端都可以跟服务端通讯,但是服务端需要回复了上一个客户端发来的消息才能收到第二个客户端发来的消息
- 例5:模拟粘包1
服务端
- import socket
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
print(conn)
print("-----------华丽丽的分割线—————————————")
print(addr)
from_msg_client01 = conn.recv(1024)
from_msg_client02 = conn.recv(1024)
print("from_msg_client01",from_msg_client01.decode("utf-8"))
print("from_msg_client02",from_msg_client02.decode("utf-8"))
conn.close()
server.close()
#server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 地址复用- 客户端
- import socket
client = socket.socket()
ip_port = ("127.0.0.1",8001)
client.connect(ip_port)- client.send(b"dating")
client.send(b"girl")- 打印结果
模拟粘包2
服务端
- import socket
import subprocess
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
from_client_msg = conn.recv(1024).decode("gbk")
sub_conn = subprocess.Popen(
from_client_msg,
shell = True,
stdout = subprocess.PIPE,
stderr=subprocess.PIPE
)
cmd_result = sub_conn.stdout.read()
conn.send(cmd_result)- 客户端
- import socket
client = socket.socket()
ip_port = ("127.0.0.1",8001)
client.connect(ip_port)
while 1:
send_msg = input("请输入指令:").strip()
client.send(send_msg.encode("gbk"))
from_server_msg = client.recv(1024)
print(from_server_msg.decode("gbk"))- ps:第二种粘包会造成结果混乱例如输入ipconfig返回的信息不全,然后在输入dir此时返回的信息是ipconfig的一部分和dir结果的一部分,再次输入ipconfig此时返回的是dir的结果
- 例6:解决粘包问题方案一 struct模块
通过strct模块里的pack和unpack来解决 首先计算数据的长度 然后通过pack打包成四个字节发送 然后在发送实际字节
服务端
- import socket
import subprocess
import struct
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
from_client_msg = conn.recv(1024).decode("gbk")
sub_conn = subprocess.Popen(
from_client_msg,
shell = True,
stdout = subprocess.PIPE,
stderr=subprocess.PIPE
)
cmd_result = sub_conn.stdout.read()
len_bytes = struct.pack("i",len(cmd_result))
conn.send(len_bytes)
conn.send(cmd_result)
客户端
- import socket
import struct
client = socket.socket()
ip_port = ("127.0.0.1",8001)
client.connect(ip_port)
while 1:
send_msg = input("请输入指令:").strip()
client.send(send_msg.encode("gbk"))- from_server_msg = client.recv(4)
- a = struct.unpack('i',from_server_msg)[0]
from_server_msg1 = client.recv(a)
print(from_server_msg1.decode("gbk"))
- 解决粘包方法2:sendall循环
接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓
,然后接收端发一个确认消息给发送端,然后发送端再发送过来后面的真实内容,接收端再来一个死循环接收完所有数据。
server端
- import socket,subprocess
ip_port=('127.0.0.1',8080)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)- s.bind(ip_port)
s.listen(5)- while True:
conn,addr=s.accept()
print('客户端',addr)
while True:
msg=conn.recv(1024)
if not msg:break
res=subprocess.Popen(msg.decode('utf-8'),shell=True,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
err=res.stderr.read()
if err:
ret=err
else:
ret=res.stdout.read()
data_length=len(ret)
conn.send(str(data_length).encode('utf-8'))
data=conn.recv(1024).decode('utf-8')
print(data)
if data == 'recv_ready':
conn.sendall(ret)
conn.close()
客户端:
- import socket,time
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(('127.0.0.1',8080))- while True:
msg=input('>>: ').strip()
if len(msg) == 0:continue
if msg == 'quit':break- s.send(msg.encode('utf-8'))
length=int(s.recv(1024).decode('utf-8'))
s.send('recv_ready'.encode('utf-8'))
send_size=0
recv_size=0
data=b''
while recv_size < length:
data+=s.recv(1024)
recv_size+=len(data)- print(data.decode('gbk'))
- 例6:socketserver实现高并发
- import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
while 1:
from_client_msg = self.request.recv(1024) # conn
print(from_client_msg.decode('utf-8'))
msg = input('to_client_msg>>>')
self.request.send(msg.encode('utf-8'))- if __name__ == '__main__':
ip_port = ('127.0.0.1',8001)
server = socketserver.ThreadingTCPServer(ip_port,MyServer)
server.serve_forever()
ps:客户端的正常写就ok
- 例子7:ftp客户端上传文件到ftp服务端
服务端
- import socket
import struct
import json
server = socket.socket()
bufsize = 1024
server.bind(("127.0.0.1",8090))
server.listen(5)
conn,addr = server.accept()- head_len = conn.recv(4) #第一次接受4个字节
head_len = struct.unpack("i",head_len)[0] #解包得到的值是一个元组,所以要加索引取值
json_head = conn.recv(head_len).decode("utf-8") #反序列化
head = json.loads(json_head)
file_size = head['filesize'] #获取长度- with open(head["filename"],'wb') as f:
while file_size:
if file_size >= bufsize:
content = conn.recv(bufsize)
f.write(content)
else:
content = conn.recv(bufsize)
f.write(content)
break
conn.close()
server.close()- 客户端
- import os
import json
import socket
import struct
client = socket.socket()
client.connect(("127.0.0.1",8090))
bufsize = 1024
head = {
'filepath':r'G:\python_project\day07',
'filename':'ftp_test',
'filesize':None
}
file_path = os.path.join(head["filepath"],head["filename"]) #拼接文件和目录
filesize = os.path.getsize(file_path) #获取文件的大小
head["filesize"] = filesize #把文件大小的值写到head字典里面- json_head = json.dumps(head) #序列化头部信息
bytes_head = json_head.encode("utf-8") #对头部信息进行编码操作
print(json_head)
print(bytes_head)- head_len = len(bytes_head) #统计头部信息的长度
pack_len = struct.pack("i",head_len) #把头部信息打包成4个字节
print(head_len)
print(pack_len)- client.send(pack_len)
client.send(bytes_head)- with open(file_path,'rb') as f:
while filesize:
if filesize >= bufsize:
content = f.read(bufsize)
client.send(content)
filesize -= bufsize
else:
content = f.read(filesize)
client.send(content)
break
client.close()
day8 socket的更多相关文章
- Python之路,Day8 - Socket编程进阶
Python之路,Day8 - Socket编程进阶 本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台 ...
- Python之旅Day8 socket网络编程
socket网络编程 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可.soc ...
- Python学习-day8 socket进阶
还是继续socket网络编程的学习. socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) Socket Fami ...
- Day8 - Python网络编程 Socket编程
Python之路,Day8 - Socket编程进阶 本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台 ...
- 第九章:Python の 网络编程基础(一)
本課主題 何为TCP/IP协议 初认识什么是网络编程 网络编程中的 "粘包" 自定义 MySocket 类 本周作业 何为TCP/IP 协议 TCP/IP协议是主机接入互网以及接入 ...
- 【目录】Python自动化运维
目录:Python自动化运维笔记 Python自动化运维 - day2 - 数据类型 Python自动化运维 - day3 - 函数part1 Python自动化运维 - day4 - 函数Part2 ...
- Python之路,Day8 - Python基础 面向对象高级进阶与socket基础
类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...
- day8
作业要求: 1.用socket写一个 ftp服务端与客户端 2.支持get put命令 作业下载地址:ftp://www.wudonghang.com/oldboy/day8.zip ...
- socket编程进阶
1. 动态导入模块 第一种方法(python解释器自己内部用的): 上图是我程序的目录结构 下面代码是动态导入模块3.py的源码: #AUTHOR:FAN lib_dir = __import__ ...
随机推荐
- nginx开启目录浏览,解决中文乱码问题
nginx开启目录浏览,解决中文乱码问题 方法如下: server { listen 80; #listen [::]:80; server_name gongzi.liwenhui.xin gz.l ...
- ajax设置头信息,读取头信息
一.设置头信息 jQuery function GetDateForServiceCustomer(userId) { $.ajax({ url: 'http://*******/api/orders ...
- [Java读书笔记] Effective Java(Third Edition) 第 3 章 对于所有对象都通用的方法
第 10 条:覆盖equals时请遵守通用约定 在不覆盖equals方法下,类的每个实例都只与它自身相等. 类的每个实例本质上都是唯一的. 类不需要提供一个”逻辑相等(logical equality ...
- JVM 内存溢出(转载~)
对于JVM的内存写过的文章已经有点多了,而且有点烂了,不过说那么多大多数在解决OOM的情况,于此,本文就只阐述这个内容,携带一些分析和理解和部分扩展内容,也就是JVM宕机中的一些问题,OK,下面说下O ...
- Rvm 进行gem安装时必须输入密码Your user account isn't allowed to install to the system RubyGems 解决方案
今天开发过程中,从master拉下代码后重启项目,想用控制台时,却发现需要密码??并且三次密码确认后还是疯狂报错. 当时第一想到是rvm版本不一致,随即则检查了版本跟gem生成,当确认rvm版本无误时 ...
- #dokcer部署code-server web版vscode+golang
codercom/code-server:latest不支持插件在线安装 codercom/code-server:v2目前为最新版1. #创建 docker rm -f vscode docker ...
- Canal——原理架构及应用场景
Canal简介 Canal是阿里开源的一款基于Mysql数据库binlog的增量订阅和消费组件,通过它可以订阅数据库的binlog日志,然后进行一些数据消费,如数据镜像.数据异构.数据索引.缓存更新等 ...
- B. Grow The Tree Codeforces Round #594 (Div. 2)
Gardener Alexey teaches competitive programming to high school students. To congratulate Alexey on t ...
- mysql数据库之索引与慢查询优化
索引与慢查询优化 知识回顾:数据都是存在硬盘上的,那查询数据不可避免的需要进行IO操作 索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构. primary key unique ...
- SpringBoot默认日志的使用方法及常用配置
SpringBoot默认采用slf4j+logback 的组合形式,但也提供对JUL.log4j2.Logback提供了默认配置. 我们使用IDEA的spring初始化创建一个springboot项目 ...