网络传输 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 ...
随机推荐
- 快速搜索多个word、excel等文件中内容
背景:要在多个文件甚至文件夹中找到文件中包含的某些内容 以win10举例: 1.打开一个文件夹 2.打开文件夹选项 3.配置搜索 4.搜索文件
- Linux系统:Centos7下搭建PostgreSQL关系型数据库
本文源码:GitHub·点这里 || GitEE·点这里 一.PostgreSQL简介 1.数据库简介 PostgreSQL是一个功能强大的开源数据库系统,具有可靠性.稳定性.数据一致性等特点,且可以 ...
- 【公告】请访问我Blog新站——superman2014 www.superman2014.com
http://www.superman2014.com 欢迎光顾 本博客不在更新!!!!
- 分治算法(C++版)
#include<iostream>using namespace std; void printArray(int array[],int length) { for (i ...
- C++语言实现顺序栈
C++语言实现顺序栈 在写C语言实现顺序栈的时候,我已经向大家介绍了栈的特点以及介绍了栈的相关操作,并利用C语言实现了相关算法.在这里小编就不在继续给大家介绍了,需要温习的可以去我的博客看看.在这篇博 ...
- matplotlib BboxBase类
2020-04-07 17:24:12 --Edit by yangray BboxBase 是 TransformNode 的子类, 同时它是所有 bounding box(平行四边形限位框) 的 ...
- 运行jmeter.bat时 提示 not able to find java executable or version
安装过好几次,这是第一次遇到运行jmeter.bat时 提示 not able to find java executable or version Please check your Java in ...
- 1年左右的Java开发经验面试者的心得
面试,相信只要踏入这行业的人都会经历,不同的公司有不同的面试流程,但是综合起来,其实还是大体一致的!只有不断的总结自己的面试经历,得出自己的技术不足点,才能更好的去查缺补漏,从而更加自信的进行面试找到 ...
- 委托的 `DynamicInvoke` 小优化
委托的 DynamicInvoke 小优化 Intro 委托方法里有一个 DynamicInvoke 的方法,可以在不清楚委托实际类型的情况下执行委托方法,但是用 DynamicInvoke 去执行的 ...
- Python—一个简单搜索引擎索引库
因为课业要求,搭建一个简单的搜索引擎,找了一些相关资料并进行了部分优化(坑有点多) 一.数据 数据是网络上爬取的旅游相关的攻略页面 这个是travels表,在索引中主要用到id和url两个字段. 页面 ...