网络传输 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 ...
随机推荐
- .git/info/refs not valid: is this a git repository?
今天用idea git提交的时候遇到了这个神奇的问题.git/info/refs not valid: is this a git repository? 看了很多网上的都不靠谱,最后自己乱点着找, ...
- 透过源码分析ArrayList运作原理
List接口的主要实现类ArrayList,是线程不安全的,执行效率高:底层基于Object[] elementData 实现,是一个动态数组,它的容量能动态增加和减少.可以通过元素下标访问对象,使用 ...
- Html 慕课园编程练习9-22
题目要求: 制作一个表格,显示班级的学生信息. 要求: 1. 鼠标移到不同行上时背景色改为色值为 #f2f2f2,移开鼠标时则恢复为原背景色 #fff 2. 点击添加按钮,能动态在最后添加一行 3. ...
- 最近准备研读thinkphp源码,ctag派上用场了
本人习惯用vim编辑器,这里ctags配置vim很方便. #在ThinkPHP源码目录(假定为/server/thinkphp)执行: $ cd /server/thinkphp $ ctags -R ...
- linux美化网址
参考博文地址 https://blog.csdn.net/qq_42527676/article/details/91356154 https://www.opendesktop.org/ Dash ...
- 队列的含义以及C语言实现顺序队列
队列,和栈一样,也是一种对数据的"存"和"取"有严格要求的线性存储结构. 什么是队列 与栈结构不同的是,队列的两端都"开口",要求数据只能从 ...
- 【python实现卷积神经网络】批量归一化层实现
代码来源:https://github.com/eriklindernoren/ML-From-Scratch 卷积神经网络中卷积层Conv2D(带stride.padding)的具体实现:https ...
- Levenshtein算法-比较两个字符串之间的相似度
package com.sinoup.util;/** * Created by Administrator on 2020-4-18. */ /** * @Title: * @ProjectName ...
- 【从零单排HBase 03】深入HBase读写
在了解HBase架构的基础上,我们需要进一步学习HBase的读写过程,一方面是了解各个组件在整个读写过程中充当的角色,另一方面只有了解HBase的真实请求过程,才能为后续的正确使用打下初步基础,毕竟, ...
- G - Pairs Forming LCM LightOJ - 1236 (质因子分解)
题解:这道题要从n的角度来考虑i和j. n可以表示为n=a1^p1*a2^p2*a3^p3.......n=lcm(i,j),那么质因子a1^p1,a1可以在i或者j中,并且p1=max(a1i,a1 ...