Python 之网络编程
# 流程描述:
#
# 1. 服务器根据地址类型(ipv4, ipv6), socket类型, 协议创建socket;
#
# 2. 服务器为socket绑定ip地址和端口号;
#
# 3. 服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开;
#
# 4. 客户端创建socket
#
# 5. 客户端打开socket, 根据服务器ip地址和端口号试图连接服务器socket;
#
# 6. 服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket
# 进入阻塞状态, 所谓阻塞即accept()方法一直等到客户端返回连接信息后才返回,开始接收下一个客户端连接请求。
#
# 7. 客户端连接成功,向服务器发送连接状态信息;
#
# 8. 服务器 accept 方法返回,连接成功;
#
# 9. 客户端向socket写入信息(或服务端向socket写入信息)
#
# 10. 服务器读取信息(或客户端读取信息)
#
# 11. 客户端关闭
# 12. 服务端关闭
1.1 相关方法及参数介绍
import socket
sk = socket.socket()
sk.bind(address)
:将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式
表示地址;sk.listen(backlog)
:开始监听传入的连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
backlog等于5,表示内核已经接到的连接请求,但服务器还没有调用accept进行处理的连接个数最大为5。这个值不可能无限大,因为要在内核中维护连接队列;sk.setblocking(bool)
: 是否阻塞(默认为True), 如果设置为False, 那么accept和recv时,一旦无数据,则报错;sk.accept()
: 接收连接并返回(conn, address), 其中conn是新的套接字对象,可以用来接收和发送数据;address是
连接客户端的地址;sk.connect(address)
: 连接到address处的套接字。一般,address的格式为元组(hostname, port),如果连接出错,
返回socket.error错误;sk.connect_ex(address)
: 同上,只不过会有返回值,连接成功时,返回0; 连接失败的时候,返回编码,例如: 10061sk.close()
: 关闭套接字;sk.recv(bufsize[, flag])
: 接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。sk.recvfrom(bufsize[,flag])
: 与recv()
类似,但返回值是 (data, address), 其中,data是包含接收数据的字符串,
address 是发送数据的套接字地址;sk.send(string[,flag])
: 将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字
节大小。即: 可能未将指定内容全部发送。sk.sendall(string[,flag])
: 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功,返回None;
失败则抛出异常。内部通过递归调用 send, 将所有内容发送出去。sk.sendto(string[,flag], address)
: 将数据发送到套接字,address的形式为元组(ipaddr, port)。返回值是发送的
字节数,该函数主要用于UDP协议;sk.settimeout(timeout)
:设置套接字操作的超时时长,timeout是一个浮点数,单位是秒。值为None,表示没有超时期。sk.getpeername()
:返回连接套接字的远程地址。返回值通常是元组(ipaddr, port);sk.getsockname()
:返回套接字自己的地址,通常是一个元组(ipaddr, port);sk.fileno()
: 套接字的文件描述符;
# 示例一: 建立连接
# sever 端
import socket
# 创建socket对象
sk = socket.socket()
# 绑定ip和端口
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)
print("waiting......")
conn = sk.accept() # 此时,返回一个包含两个元素的元组
print(conn)
# client 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
# 示例二: 服务端发送,客户端接收
# server 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
conn, addr = sk.accept()
# 发送消息
msg = input('>>>')
# conn.send(msg), 此处会报错: a bytes-like object is required, not 'str'
conn.send(bytes(msg, 'utf8'))
# client 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
# 接收消息
data = sk.recv(1024) # 此处,客户端会阻塞,等待服务端发送消息
print(str(data, 'utf8'))
# 示例三: 客户端发送, 服务端接收
# server 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
conn, addr = sk.accept()
# 接收消息
data = conn.recv(1024) # 注意,服务端使用 conn 来收发数据
print(data)
conn.close() # 关闭连接
# client 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
# 发送消息
sk.send(bytes('大家好', 'utf8'))
sk.close()
# 示例四: 不间断聊天
# server 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
conn, addr = sk.accept()
while True:
data = conn.recv(1024)
if not data:
break
print(str(data, 'utf8'))
msg = input('>>>')
conn.send(bytes(msg, 'utf8'))
conn.close()
# client 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
while True:
msg = input('>>>')
if msg == 'exit':
break
sk.send(bytes(msg, 'utf8'))
data = sk.recv(1024)
print(str(data, 'utf8'))
sk.close()
# 示例五:
# server 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
while True:
conn, addr = sk.accept() # 某一个客户端关闭后,可以接收另外一个客户端发来的消息
print(addr)
while True:
try:
data = conn.recv(1024)
except Exception:
break
if not data:
break
print(str(data, 'utf8'))
msg = input('>>>')
conn.send(bytes(msg, 'utf8'))
sk.close()
# 示例六: 远程执行命令
# server 端
import socket
import subprocess
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
while True:
conn, addr = sk.accept()
print(addr)
while True:
data = conn.recv(1024)
if not data:
break
print(str(data, 'utf8'))
obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE)
cmd_result = obj.stdout.read()
# 只能传输bytes类型数据,int首先转成str,然后转成bytes
result_len = bytes(str(len(cmd_result)), 'utf8') # 获取传输内容的大小
conn.sendall(result_len)
conn.recv(1024) # 解决粘包问题
conn.sendall(cmd_result)
sk.close()
# client 端
import socket
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
while True:
msg = input('>>>')
if msg == 'exit':
break
sk.send(bytes(msg, 'utf8'))
result_len = int(str(sk.recv(1024), 'utf8'))
sk.sendall('ok')
data = bytes() # 空字节
while len(data) != result_len:
data += sk.recv(1024)
print(str(data, 'utf8'))
# 示例七: 上传文件
# server 端
import socket
import os
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
while True:
conn, addr = sk.accept()
while True:
data = conn.recv(1024)
cmd, file_name, file_size = str(data, 'utf8').split('|')
path = os.path.join(BASE_DIR, 'a', file_name)
file_size = int(file_size)
f = open(path, 'ab')
has_receive = 0
while has_receive != file_size:
data = conn.recv(1024)
f.write(data)
has_receive += len(data)
f.close()
sk.close()
# client 端
import socket
import os
sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
BASE_DIR=os.path.dirname(os.path.abspath(__file__))
while True:
msg = input('>>>').strip() # 规定输入格式为: post|a.jpg(命令|路径), strip()去除首尾空格
cmd, path = msg.split('|')
# 路径拼接, 因为传入的path可能为 a/b/a.jpg
path = os.path.join(BASE_DIR, path)
# 获取文件名称
filename = os.path.basename(path)
# 获取文件大小
file_size = os.stat(path).st_size
file_info = 'post|%s|%s' % (filename,file_size)
# 向服务端发送消息
sk.sendall(bytes(file_info, 'utf8'))
# 向服务端发送文件内容
f = open(path, 'rb') # 以bytes的格式读取数据
has_sent = 0
while has_sent != file_size:
data = f.read(1024) # 每次发送1024字节数据
sk.sendall(data)
has_sent += len(data)
f.close()
print('上传成功!')
2. socketserver 模块
# 示例一: server端并发聊天
# server 端
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
print('服务端启动...')
while True:
conn = self.request
print(self.client_address)
while True:
client_data = conn.recv(1024)
print(str(client_data, 'utf8'))
print('waiting......')
conn.sendall(client_data)
conn.close()
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1', 8000), MyServer)
server.serve_forever()
# client 端
import socket
ip_port = ('127.0.0.1', 8000)
sk = socket.socket()
sk.connect(ip_port)
print('客户端启动:')
while True:
msg = input('>>>')
sk.sendall(bytes(msg, 'utf8'))
if msg == 'exit':
break
server_response = sk.recv(1024)
print(str(server_response, 'utf8'))
sk.close()
参考资料:
Python 之网络编程的更多相关文章
- python之网络编程
本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...
- Python的网络编程--思维导图
Python的网络编程--思维导图
- Python高级网络编程系列之第一篇
在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...
- python基础网络编程--转
python之网络编程 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的 ...
- python 基础网络编程2
python 基础网络编程2 前一篇讲了socketserver.py中BaseServer类, 下面介绍下TCPServer和UDPServer class TCPServer(BaseServer ...
- python 基础网络编程1
python 基础网络编程1 Source code: Lib/socketserver.py lib的主目录下有一个sockserver.py文件, 里面是python基本的网络编程模型 共有一个b ...
- python select网络编程详细介绍
刚看了反应堆模式的原理,特意复习了socket编程,本文主要介绍python的基本socket使用和select使用,主要用于了解socket通信过程 一.socket模块 socket - Low- ...
- Python Socket 网络编程
Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...
- python多线程网络编程
背景 使用过flask框架后,我对request这个全局实例非常感兴趣.它在客户端发起请求后会保存着所有的客户端数据,例如用户上传的表单或者文件等.那么在很多客户端发起请求时,服务器是怎么去区分不同的 ...
- python中网络编程基础
一:什么是c\s架构 1.c\s即client\server 客户端\服务端架构. 客户端因特定的请求而联系服务器并发送必要的数据等待服务器的回应最后完成请求 服务端:存在的意义就是等待客户端的请求, ...
随机推荐
- 解决eclipse启动tomcat报错:Could not load the Tomcat server configuration at \Servers\Tomcat v6.0 Server at localhost-config. The Servers project is closed.
报错信息已经说的很清楚了:The Servers project is closed.如图 打开即可: 另外,如果你修改了Servers project的name(比如说把这里的Servers改成了X ...
- 16位结构的CPU,8086给出物理地址的方法
.16位结构的CPU 概括地讲,16位结构(16位机,字长为16位等常见说法,与16位结构的含义相同)描述了一个CPU具有下面几方面结构特性: 1.运算器一次最多可以处理16位的数据结构 2.寄存器的 ...
- dfs带状态改变的做法
所谓带状态改变是指:在搜索到某个位置的时候,状态发生改变,继续计算步数. 给一个例题: 蒜头君要回家,但是他家的钥匙在他的朋友花椰妹手里,他要先从花椰妹手里取得钥匙才能回到家.花椰妹告诉他:“你家的钥 ...
- 基于js鼠标拖动图片排序
分享一款基于js的图片排序效果.鼠标拖动图片,重新排列图片的排列顺序.该插件适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗.效果图如下: 在线 ...
- love2d教程32--碎图打包器texturepacker
texturepacker是一个碎图打包器,可以把小图合并成一张大图,并对大图做优化.我用的是特别版(只好用xx版了, 不然导出的图片会被变成红色),网盘下载,文件会提示有毒,我也是在网上找的,其实是 ...
- 浅析StackTrace
我们在学习函数调用时,都知道每个函数都拥有自己的栈空间.一个函数被调用时,就创建一个新的栈空间.那么通过函数的嵌套调用最后就形成了一个函数调用堆栈.在c#中,使用StackTrace记录这个堆栈.你可 ...
- Xml解析之PULL解析 例1
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id=" ...
- Spider Studio 界面功能布局
SS是Spider Studio (采集工作站) 的简称, 这是由GDT团队开发的一款互联网数据采集开发工具. 它以浏览器为基础, 运用JQuery技术, 结合脚本化C#的强大功能, 能够轻松解决各类 ...
- 【安卓】自己定义基于onDraw的随意动画(不不过平移/旋转/缩放/alpha)、!
思路: 1.基于时间的显示映射.如:给定度数,显示圆弧,加上时序,就可以有圆弧动画的效果 2.给定时序. 用于驱动动画的一帧帧绘制 方案一.基于ObjectAnimator.动画运作时会调用degre ...
- "crsctl check crs" command hangs at EVMD check
Pre-11gR2: "crsctl check crs" command hangs at EVMD check (文档 ID 1578875.1) APPLIES TO: ...