网络传输 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 ...
随机推荐
- Spring ApplicationContext 容器
Spring ApplicationContext 容器 Application Context 是 BeanFactory 的子接口,也被成为 Spring 上下文. Application Con ...
- 玩转控件:对Dev的GridControl控件扩展
缘由 一切实现来源于需求,目的在于不盲目造轮子,有小伙伴儿在看了<玩转控件:对Dev中GridControl控件的封装和扩展>文章后,私信作者说,因公司业务逻辑比较复杂,展示字段比较多,尤 ...
- MFC之使用blat发送邮件
blat的下载地址:http://www.blat.net 我用它进行了smtp服务的邮件发送.这里我使用的qq邮箱,qq邮箱使用的密码是授权码,可以再qq邮箱设置里面开启smtp服务.下载下来是文件 ...
- CentOS 7 Docker安装
1. uname -a 查询机器信息,确保CPU为64位,且Linux内核在3.10版本以上 2. 更新yum包: yum update 3. 在 /etc/yum.repos.d下创建 docker ...
- uni-app在线引入阿里字体图标库
第一步 在app.vue中引入阿里字体图标库 第二步 在任意页面使用就可以了 <view class="item" v-for="(value,index) in ...
- MTK Android 读取SIM卡参数,获取sim卡运营商信息
android 获取sim卡运营商信息(转) TelephonyManager tm = (TelephonyManager)Context.getSystemService(Context.TE ...
- (js描述的)数据结构[字典](7)
(js描述的)数据结构[字典](7) 一.字典的特点 1.字典的主要特点是一一对应关系. 2.使用字典,剋通过key取出对应的value值. 3.字典中的key是不允许重复的,而value值是可以重复 ...
- ArrayList、LinkedList和Vector源码分析
ArrayList.LinkedList和Vector源码分析 ArrayList ArrayList是一个底层使用数组来存储对象,但不是线程安全的集合类 ArrayList的类结构关系 public ...
- 创建堆(python)
创建最大(小)堆 二叉堆本质上是一种完全二叉树,存储方式并不是链式存储,而是顺序存储 堆操作:插入(叶子节点上调),删除(堆顶元素下沉) 堆创建:非叶子节点下沉(从最后一个非叶子节点开始) 最小堆: ...
- golang开发:环境篇(七) Go mod 使用
Glide用的好好的,为什么要使用Modules 在 Go 1.11 中 ,官方加入package management tool,称为Go Modules.Go mod 没有出现之前,用的最多的包管 ...