网络传输 socket
一、Socket语法及相关
前言:osi七层模型:
Socket概念:
socket和file的区别:
- file模块是针对某个指定文件进行【打开】【读写】【关闭】
- socket模块是针对 服务器端 和 客户端Socket进行 【打开】【读写】【关闭】
socket语法:
AF_CAN the protocol should be one of CAN_RAW or CAN_BCM. If fileno is specified, the other arguments are ignored, causing the socket with the specified file descriptor to return. Unlike socket.fromfd(), fileno will return the same socket and not a duplicate. This may help close a detached socket using socket.close().socket实例的常用方法:
二、socket实例
伪代码:
服务端:
import socket #导入socket
server=socket.socket() #定义服务端的协议类型,默认为TCP/IP。socket.socket()默认为socket.socket(family=AF_INET,type=SOCK_STREAM)
listen('0.0.0.0',80) 设置默认的监听ip+port
waiting() 服务端指定端口等待接收来自客户端的信息
recv() 接收信息
send() 返回信息
客户端:
import socket #导入socket
client=socket.socket() #定义服务端的协议类型,默认为TCP/IP。socket.socket()默认为socket.socket(family=AF_INET,type=SOCK_STREAM)
connect((server.ip,server.port))
socket.send(message)
socket.recv() 接收信息
socket.close()
实例1:实现简单的服务端和客户端的单次数据传输
服务端:
import socket
server=socket.socket() #声明socket类型,同时生成socket连接对象
server.bind(('localhost',8888)) #绑定ip,port
server.listen() #开始监听
print('等待客户端的连接...')
conn,addr=server.accept() #接受并建立与客户端的连接,程序在此处开始阻塞,直到有客户端连接进来...
'''conn就是客户端连进来而在服务器端为其生成的一个连接实例'''
print('新连接:',addr) #接收客户端的(host,port)到addr
data=conn.recv(1024) #一次接受客户端信息为1024bytes
print('收到消息:',data)
conn.send(data.decode().lower().encode()) #将英文字符串全部转换为小写。由于data是bytes类型,先将bytes类型decode成unicode的str,对字符串进行操作以后,再进行encode()为bytes类型传输
'''经过测试data.lower()一样可以执行成功,因此,bytes类型的字符串也可以进行字符串操作''' server.close()
客户端:
import socket
client=socket.socket() #默认ipv4,TCP/IP。声明socket类型,同时生成socket连接对象。
client.connect(('localhost',8888))
'''连接到address处的套接字。client.connect(address),其中address的格式为元组(hostname.port),
如果连接出错,返回socket.error错误。
此外,sk.connect_ex(address) 连接成功返回0,连接失败时返回编码,如:10086.'''
client.send('Hello World'.encode('utf-8')) #客户端向服务端发送数据
data=client.recv(1024) #接收来自服务端的数据,1024的单位是字节,1024 bytes=1 kb
print('recv:',data.decode())
client.close()

服务端:
import socket
server=socket.socket() #声明协议类型
ip_port=('localhost',8888)
server.bind(ip_port) #绑定ip,port
server.listen() # 开始监听
print('等待客户端的连接...') conn, addr = server.accept() # 接受并建立与客户端的连接,程序在此处开始阻塞,直到有客户端连接进来...
print('新连接:', addr)
while True: #多次命令的交互主要在于循环体建立在此,conn实例化的连接已经完成,不在循环体内。
print('等待新指令')
data = conn.recv(1024)
print('收到消息:', data)
conn.send(data.lower())
server.close()
客户端:
import socket
client=socket.socket() #默认ipv4,TCP/IP。声明socket类型,同时生成socket连接对象。
ip_port=('localhost',8888)
client.connect(ip_port)
while True:
msg = input('>>:').strip()
client.send(msg.encode('utf-8')) # 客户端向服务端发送数据
data = client.recv(1024) # 接收来自服务端的数据,1024的单位是字节,1024 bytes=1 kb
print('recv:', data.decode())
client.close()
实例3:优化:解决输入空信息时阻塞问题
由于在client中发送空数据,server.client(1024)没有接收到数据,它会一直等着收数据,导致程序阻塞。所以client端也要加上对发送的数据是否为空字符集做出判断。
服务端:
import socket
server=socket.socket() #声明协议类型
ip_port=('localhost',8888)
server.bind(ip_port) #绑定ip,port
server.listen() # 开始监听
print('等待客户端的连接...')
conn, addr = server.accept() # 接受并建立与客户端的连接,程序在此处开始阻塞,直到有客户端连接进来...
print('新连接:', addr)
while True: #多次命令的交互主要在于循环体建立在此,conn实例化的连接已经完成,不在循环体内。
print('等待新指令')
data = conn.recv(1024)
print('收到消息:', data)
conn.send(data.lower())
server.close()
客户端:
import socket
client=socket.socket() #默认ipv4,TCP/IP。声明socket类型,同时生成socket连接对象。
ip_port=('localhost',8888)
client.connect(ip_port)
while True:
msg = input('>>:').strip()
if len(msg)==0:continue
client.send(msg.encode('utf-8')) # 客户端向服务端发送数据
data = client.recv(1024) # 接收来自服务端的数据,1024的单位是字节,1024 bytes=1 kb
print('recv:', data.decode())
client.close()
实例4:优化:实现多进程的等待访问服务端
服务端:
import socket
server=socket.socket()
ip_port=('localhost',8888)
server.bind(ip_port) #绑定ip,port
server.listen() # 开始监听
print('等待客户端的连接...')
while True:
conn, addr = server.accept() # 接受并建立与客户端的连接,程序在此处开始阻塞,直到有客户端连接进来...
print('新连接:', addr)
while True:
print('等待新指令')
data = conn.recv(1024)
print('收到消息:', data)
conn.send(data.lower())
server.close()
客户端:
import socket
client=socket.socket() #默认ipv4,TCP/IP。声明socket类型,同时生成socket连接对象。
ip_port=('localhost',8888)
client.connect(ip_port)
while True:
msg = input('>>:').strip()
client.send(msg.encode('utf-8')) # 客户端向服务端发送数据
data = client.recv(1024) # 接收来自服务端的数据,1024的单位是字节,1024 bytes=1 kb
print('recv:', data.decode())
client.close()
import socket
server=socket.socket()
ip_port=('localhost',8888)
server.bind(ip_port) #绑定ip,port
server.listen() # 开始监听
print('等待客户端的连接...')
while True:
conn, addr = server.accept() # 接受并建立与客户端的连接,程序在此处开始阻塞,直到有客户端连接进来...
print('新连接:', addr)
while True:
print('等待新指令')
data = conn.recv(1024)
print('收到消息:', data)
if not data:break
conn.send(data.lower())
server.close()
服务端:
import socket,os
server=socket.socket()
ip_port=('localhost',8888)
server.bind(ip_port) #绑定ip,port
server.listen() # 开始监听
print('等待客户端的连接...')
while True:
conn, addr = server.accept() # 接受并建立与客户端的连接,程序在此处开始阻塞,直到有客户端连接进来...
print('addr:',addr)
while True:
data = conn.recv(1024)
if not data:break
res=os.popen(data.decode()).read()
length=len(res.encode())
'''为了确保长度不会因为不同的字符编码格式下中英文字符的字节数大小,统一都取格式为bytes的文本字节总长度。'''
print('lenth of res:',length)
if length==0:
res='cmd has no output...'
conn.send(str(length).encode())
print('file total size has been send:',length)
buffer_recv=conn.recv(1024)
print('continue')
conn.sendall(res.encode())
print('成功发送命令执行结果')
server.close()
客户端:
import socket
client=socket.socket() #默认ipv4,TCP/IP。声明socket类型,同时生成socket连接对象。
ip_port=('localhost',8888)
client.connect(ip_port)
while True:
msg = input('>>:').strip()
if len(msg)==0:continue
client.send(msg.encode('utf-8')) # 客户端向服务端发送数据
length=int(client.recv(1024).decode())
print('接收文件的总大小为:',length)
client.send('准备好接收数据了...'.encode())
receive_size=0
cmd_res=b''
# f=open('test.txt','w')
while receive_size != length:
data = client.recv(1024) # 接收来自服务端的数据,1024的单位是字节,1024 bytes=1 kb
receive_size+=len(data)
cmd_res+=data
print('文件内容已经成功传输过来:',cmd_res.decode())
client.close()
三、简单的ftp实现:文件的传输
ftp server
1. 读取文件名
2. 检测文件是否存在
3. 打开文件
4. 检测文件大小
5. 发送文件大小给客户端
6. 等客户端确认
7. 开始边读边发数据
8. 发送md5
ftp client
1. 发送打开文件命令
2. 从客户端收到即将接收的文件大小
3. 发送给服务端,客户端收到(防止粘包)
4. 打开新文件
5. 接收文件,边收边写入,边写md5
6. 判断收到文件的大小和之前收到的客户端发送的文件大小是否一致,截取最后的md5加密数据
7. 关闭文件
8. 接收md5
9. 最后对两个md5进行比较,确认文件是否完整的传入客户端,且没发生数据粘包情况导致的文件混乱
实例:
服务端:
import socket,os,hashlib
server=socket.socket()
ip_port=('localhost',8888)
server.bind(ip_port)
server.listen(5)
while True:
conn,addr=server.accept()
print('收到客户端的访问信息了...')
while True:
cmd = conn.recv(1024)
print('收到来自客户端的命令', cmd)
if not cmd: break # 判断是否为空
if cmd.decode().startswith('get'):
order, filename = cmd.decode().split()
print('客户端想要得到的文件为', filename)
if os.path.isfile(filename):
f = open(filename, 'rb')
file_size = os.stat(filename).st_size
conn.send(str(file_size).encode())
print('向客户端发送的文件总大小为', file_size)
conn.recv(1024)
m = hashlib.md5()
count = 0
for line in f:
m.update(line)
conn.send(line) # 边读边传
count += 1
print('已经向客户端传入文件%s次' % count)
f.close()
print('文件的md5为', m.hexdigest())
conn.send(m.hexdigest().encode())
print('与该客户端的交互完成,等待下一个客户端的连接')
server.close()
客户端:
import socket,os,hashlib
client=socket.socket()
client.connect(('localhost',8888))
while True:
cmd=input('>>:').strip()
if not cmd:continue
order,filename=cmd.split()
client.send(cmd.encode()) #向客户端发送打开文件的命令 格式指定为get filename
#接收即将收到的文件的大小
file_size=int(client.recv(1024).decode())
print(file_size)
client.send(b'recv file size')
received_file_size=0
received_file_lines=b''
f=open(filename+'new','wb')
m=hashlib.md5()
while received_file_size<file_size:
if file_size-received_file_size>1024:
size=1024
else:
size=file_size-received_file_size
line=client.recv(size)
received_file_size+=len(line)
received_file_lines+=line
f.write(line)
m.update(line)
else:
print('持续接收的文件大小为',received_file_size,'总文件大小为',file_size)
print('接收的文件的md5为',m.hexdigest())
f.close()
file_md5=client.recv(1024)
print('最后接收服务端的md5',file_md5)
client.close()
while received_file_size<file_size:
if file_size-received_file_size>1024:
size=1024
else:
size=file_size-received_file_size
line=client.recv(size)
四、Socket Server实现多并发
种类:
There are five classes in an inheritance diagram, four of which represent synchronous servers of four types:

使用socketserver的方法步骤:
你必须自己创建一个请求处理类class RequestHandle,并且这个类要继承BaseRequestHandler,并且还有重写父亲类BaseRequestHandleer里的handle(). 第二步:Second, you must instantiate one of the server classes, passing it the servers address and the request handler class.
你必须实例化socketserver.TCPServer/socketserver.UDPServer ,并且传递server ip 和 你上面创建的请求处理类 给这个TCPServer 第三步:Then call the handle_request() or serve_forever() method of the server object to process one or many requests.
调用服务器的handle_request()方法或serve_forever()方法来确定进程中是处理一个还是多个请求。
server.handle_request() #只处理一个请求
server.serve_forever() #处理多个请求,永远执行 最后:Finally, call server_close() to close the socket.
最后调用server_close()关闭服务器。
标准使用格式:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler): #每一个客户端的请求都会实例化一个MyTCPHadndler()
def handle(self): #所有和客户端的交互都是handle在处理
while True:
try:
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0])) #格式化客户端的ip地址
print(self.data)
self.request.send(self.data.upper())
except ConnectionResetError as e:
print("err",e)
break
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
最简单实例应用:利用socketserver,客户端交互与服务端的交互收发数据
服务端:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler): #每一个客户端的请求都会实例化一个MyTCPHadndler()
def handle(self): #所有和客户端的交互都是handle在处理
while True:
try:
self.data = self.request.recv(1024).strip() #
print("{} wrote:".format(self.client_address[0])) #格式化客户端的ip地址
print(self.data)
if not self.data:break
self.request.send(self.data.upper())
except ConnectionResetError as e:
print("err",e)
break
if __name__ == "__main__":
HOST, PORT = "localhost", 101
# Create the server, binding to localhost on port 9999
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) #ThreadingTCPServer支持多线程
server.serve_forever()
客户端:
import socket
client=socket.socket()
client.connect(('localhost',101))
while True:
cmd=input('>>:').strip()
client.send(cmd.encode())
data=client.recv(1024)
print('recv:',data.decode())
client.close()
- class
socketserver.ForkingTCPServer 在windows不好用 - class
socketserver.ForkingUDPServer - class
socketserver.ThreadingTCPServer - class
socketserver.ThreadingUDPServer
网络传输 socket的更多相关文章
- java--基于socket的网络传输开发
继http://blog.csdn.net/gaopeng0071/article/details/10959845此文章内容展开的研究. socket传输是基于tcp的网络传输协议进行的传输,tcp ...
- java socket 多线程网络传输多个文件
http://blog.csdn.net/njchenyi/article/details/9072845 java socket 多线程网络传输多个文件 2013-06-10 21:26 3596人 ...
- python网络编程-socket编程
一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层 ...
- ASP.NET知识总结(1.网络传输层)
1.网络传输层 1应用层(HTTP.FTP.SMTP)报文Message 2传输层(TCP.UDP)报文段Segment,为运行在不同主机上的应用程序进程间提供数据 传输服务.通过套接字(Socket ...
- 操作系统,windows编程,网络,socket
首发:个人博客,更新&纠错&回复 之前关于c/s的一篇博文只记了思路没记代码,而且表达不清晰,事后看不知所云,这个习惯要改. 这十几天学了点关于操作系统.windows编程和网络,主要 ...
- 网络编程socket基本API详解(转)
网络编程socket基本API详解 socket socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信. socket ...
- java网络编程socket解析
转载:http://www.blogjava.net/landon/archive/2013/07/02/401137.html Java网络编程精解笔记2:Socket详解 Socket用法详解 在 ...
- Android IOS WebRTC 音视频开发总结(五七)-- 网络传输上的一种QoS方案
本文主要介绍一种QoS的解决方案,文章来自博客园RTC.Blacker,欢迎关注微信公众号blacker,更多详见www.rtc.help QoS出现的背景: 而当网络发生拥塞的时候,所有的数据流都有 ...
- 解决TCP网络传输“粘包”问题
当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API).TCP/IP传输层有两个并列的协议:TCP和UDP.其中TCP(transport contro ...
随机推荐
- IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试
IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试 目的不是为了编写TSC2007驱动,是为了学习IIC驱动的编写,读一下TSC2007的ADC数据进行练习,, Linux主机驱动和外设驱 ...
- 家庭记账本app进度之关于tap的相关操作1
今天还主要学习关于怎样制作微信的先关的tap. 今天的主要成果是已经了解了相关的技术,以及相关的思路.代码经过一个下午的编写,基本接近尾声. 更详细的实验代码,以及相关的知识点将在明天完善后进行发表. ...
- 【python实现卷积神经网络】激活函数的实现(sigmoid、softmax、tanh、relu、leakyrelu、elu、selu、softplus)
代码来源:https://github.com/eriklindernoren/ML-From-Scratch 卷积神经网络中卷积层Conv2D(带stride.padding)的具体实现:https ...
- spark本地开发环境搭建及打包配置
在idea中新建工程 删除新项目的src,创建moudle 在父pom中添加spark和scala依赖,我们项目中用scala开发模型,建议scala,开发体验会更好(java.python也可以) ...
- 01-启动jmeter目录功能
1.bin :存储了jmeter的可执行程序,如启动脚本.配置程序 docs: api扩展文档存放 lib: lib\ext 存储了jmeter的整合的功能(如.jar文件程序,和第三方 ...
- 树状数组模板--Color the ball
Color the ball HDU - 1556 N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电 ...
- 数据表记录包含表索引和数值(int范围的整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照key值升序进行输出
此题如果直接使用有序的TreeMap就不需要这样折腾: 1.map的key值唯一性,故就不在需要set集合来去重 2.使用map后利用key的唯一性,把序列号相同的数据直接加在一起,代码会很简洁 pa ...
- Julia基础语法复数和分数
1.复数 2.分数
- 怎样才能拥有营销号生成器功能?python帮你实现
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http ...
- C - Highways poj1751最小生成树
The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has a very poor system of p ...