python --- 网络编程Socket

简介:   网络编程    定义:所为网络编程即是对信息的发送和接收。    主要工作:      (1)发送端:将信息以规定的协议组装成数据包。      (2)接收端:对收到的数据包解析,以提取所需要的信息。

  网络编程

    定义:所为网络编程即是对信息的发送和接收。

    主要工作:

      (1)发送端:将信息以规定的协议组装成数据包。

      (2)接收端:对收到的数据包解析,以提取所需要的信息。

 

    Socket:两个在网络上的程序通过一个双向的通信连接,实现数据的交换,此连接的一端称为一个socket。

      Socket的本质:Socket是一个编程接口(API),TCP/IP协议需要向开发者提供做网络开发用的接口,这就是Socket接口,它是对TCP/IP协议网络通信的封装。

 

  python中用有标准库socket,要进行socket编程,只需导入这个模块即可。

  例一(实现一个单对单,只能发送一次消息的一次性服务端和客户端):

 1 #服务端
 2 import socket
 3 
 4 address = ("localhost", 6666)  #写明服务端要监听的地址,和端口号
 5 server = socket.socket()        #生成一个socket对象
 6 server.bind(address)            #用socket对象绑定要监听的地址和端口
 7 server.listen()                 #开始监听
 8 
 9 conn,addr = server.accept()     #等带新连接接入服务端,返回一个新的socket对象和地址,地址格式同前面格式
10 '''
11 Wait for an incoming connection.  Return a new socket
12 representing the connection, and the address of the client.
13 '''
14 data = conn.recv(1024)         #接收信息,写明要接收信息的最大容量,单位为字节
15 print("server recv:", data)
16 conn.send(data.upper())       #对收到的信息处理,返回到客户端
17 
18 server.close()      #关闭服务端
socket_server
 1 #客户端
 2 import socket
 3 
 4 address = ('localhost', 6666)    #写明要发送消息的服务端的地址和端口号
 5 client = socket.socket()
 6 client.connect(address)           #连接服务端
 7 
 8 client.send(b"hell world")      #发送信息,注意在python3中socket的发送只支持bytes类型
 9 data = client.recv(1024)         #等待接收服务端返回的信息
10 print("client recv:", data)
11 
12 client.close()                   #关闭客户端
socket_client

   例二(对上面的代码进行改进,可以挂起多个连接,使每个连接可以进行多次对话且上一个连接断开后下一个连接马上接入):

 1 #服务端
 2 import socket
 3 
 4 address = ("localhost", 6666)  #写明服务端要监听的地址,和端口号
 5 server = socket.socket()        #生成一个socket对象
 6 server.bind(address)            #用socket对象绑定要监听的地址和端口
 7 server.listen(5)                 #开始监听
 8 
 9 while True:
10     #一条连接关闭后,接入下一条连接
11     conn,addr = server.accept()     #等带新连接接入服务端,返回一个新的socket对象和地址,地址格式同前面格式
12     '''
13     Wait for an incoming connection.  Return a new socket
14     representing the connection, and the address of the client.
15     '''
16     while True:
17         #使其可以接收多次消息
18         data = conn.recv(1024)         #接收信息,写明要接收信息的最大容量,单位为字节
19         # 没收到消息,断开本次连接
20         if not data:
21             break
22         print("server recv:", data)
23         conn.send(data.upper())       #对收到的信息处理,返回到客户端
24 
25 server.close()      #关闭服务端
socket_server2
 1 #客户端
 2 import socket
 3 
 4 address = ('localhost', 6666)    #写明要发送消息的服务端的地址和端口号
 5 client = socket.socket()
 6 client.connect(address)           #连接服务端
 7 
 8 while True:
 9     #使其可以向服务端多次发送消息
10     msg = input(">>>:").strip()
11     #如果发送的消息为空,则不再发送
12     if len(msg) == 0:
13         break
14     msg = msg.encode('utf-8')   #将要发送的消息转为bytes类型
15     client.send(msg)      #发送信息,注意在python3中socket的发送只支持bytes类型
16     data = client.recv(1024)         #等待接收服务端返回的信息
17     print("client recv:", data.decode())
18 
19 client.close()                   #关闭客户端
socket_client2

  例三(对例二稍加改造,就可实现一个简单的ssh的服务端和客户端):

 1 #服务端
 2 import socket
 3 import os
 4 
 5 address = ("localhost", 8888)  #写明服务端要监听的地址,和端口号
 6 server = socket.socket()        #生成一个socket对象
 7 server.bind(address)            #用socket对象绑定要监听的地址和端口
 8 server.listen()                 #开始监听
 9 
10 while True:
11     #一条连接关闭后,接入下一条连接
12     conn,addr = server.accept()     #等带新连接接入服务端,返回一个新的socket对象和地址,地址格式同前面格式
13     '''
14     Wait for an incoming connection.  Return a new socket
15     representing the connection, and the address of the client.
16     '''
17     while True:
18         data = conn.recv(1024)         #接收信息,写明要接收信息的最大容量,单位为字节
19         # 没收到消息,断开本次连接
20         if not data:
21             break
22         cmd_result = os.popen(data.decode(), 'r').read()             #执行命令,将命令执行结果保存到cmd_result
23         if len(cmd_result) == 0:
24             '''命令执行结果为空,认为接收到错误命令'''
25             cmd_result = "It's a wrong command..."
26 
27         while True:
28             conn.send(str(len(cmd_result)).encode('utf-8'))     #发送命令执行结果的长度
29             confirm = conn.recv(1024).decode()
30             '''客户端确认收到数据长度,发送数据,否则重传;且解决粘包问题'''
31             if confirm == "OK":
32                 conn.send(cmd_result.encode('utf-8'))       #对收到的信息处理,返回到客户端
33                 break
34             else :
35                 continue
36 
37 
38 server.close()      #关闭服务端
ssh_socket_server
 1 import socket
 2 
 3 address = ("localhost", 8888)
 4 client = socket.socket()
 5 client.connect(address)
 6 
 7 while True:
 8     cmd = input("(command)>>>:").strip()
 9     if len(cmd) == 0:
10         '''发送空命令时,结束本次循环'''
11         continue
12     if cmd == "#exit":
13         '''当检测到#exit,客户端与服务端断开连接'''
14         break
15 
16     client.send(cmd.encode())        #向服务端发送命令
17 
18 
19     cmd_result = ''      #目前已接收的数据
20     size_data = 0        #目前已接收数据的长度
21     size_cmd_result = int(client.recv(1024).decode())  #接收命令执行结果的长度
22     client.send("OK".encode("utf-8"))  #向服务端确认收到数据长度
23     while size_data < size_cmd_result:
24         '''命令的执行结果可能大于设置的接收buffersize,多次接收'''
25         data = client.recv(1024).decode()           #每次接收的数据
26         size_data += len(data)
27         cmd_result += data
28 
29     print(cmd_result)
30 
31 client.close()
ssh_socket_client

     注:提供另一种接收思路,服务端可以在每次返送完命令执行结果后,再发送一个结束标志,当客户端检测到结束标志时停止循环接收。

  例四(改造例三,就可以实现一个简单的ftp的服务端和客户端)

 1 #/usr/bin/python3
 2 #服务端
 3 import socket
 4 import os
 5 import hashlib
 6 
 7 address = ("0.0.0.0", 8888)  #写明服务端要监听的地址,和端口号
 8 server = socket.socket()        #生成一个socket对象
 9 server.bind(address)            #用socket对象绑定要监听的地址和端口
10 server.listen()                 #开始监听
11 
12 while True:
13     #一条连接关闭后,接入下一条连接
14     conn,addr = server.accept()     #等带新连接接入服务端,返回一个新的socket对象和地址,地址格式同前面格式
15     '''
16     Wait for an incoming connection.  Return a new socket
17     representing the connection, and the address of the client.
18     '''
19     while True:
20         content = os.popen('ls', 'r').read()
21         conn.send(content.encode('utf-8'))      #与客户端建立连接后,将服务端有哪些文件发给客户端,供客户端选择
22         filename = conn.recv(1024).decode()      #接收客户端发来的文件名
23 
24         if os.path.isfile(filename):
25             '''文件存在,开始发送文件'''
26             file_md5 = hashlib.md5()             #初始化MD5对象,用于传输完成后的校验
27             file_size = os.stat(filename)[6]     #读取文件大小
28             conn.send(str(file_size).encode('utf-8'))      #将文件size发给客户端
29             confirm = conn.recv(1024).decode()             #等待客户端确认接收
30             if confirm == "OK":
31                 '''发送文件数据'''
32                 with open(filename, 'rb') as fp:
33                     for line in fp:
34                         file_md5.update(line)
35                         conn.send(line)
36 
37                 client_md5 = conn.recv(1024).decode()        #传输完成后接收客户端发来的MD5
38                 if file_md5.hexdigest() == client_md5:
39                     '''确认文件传输未出错'''
40                     conn.send("Success...".encode('utf-8'))
41                 else :
42                     '''文件传输出错,提示客户端删除重传'''
43                     conn.send("This file is changed, please delete it and try again...".encode('utf-8'))
44 
45             #客户端未确认接收,重试
46             else :
47                 conn.send("Error, try again...".encode('utf-8'))
48                 continue
49 
50         else :
51             '''文件不存在,让客户端重新发送文件名'''
52             conn.send("The file name is wrong and try again".encode('utf-8'))
53 
54 server.close()      #关闭服务端
ftp_socket_server
 1 #/usr/bin/python3
 2 import socket
 3 import hashlib
 4 
 5 address = ("192.168.56.50", 8888)
 6 client = socket.socket()
 7 client.connect(address)
 8 
 9 while True:
10     content = client.recv(4096)             #接收并打印服务端有哪些文件
11     print("Files List".center(75, '-'))
12     print(content.decode())
13 
14     #向服务端发送想要接收的文件名
15     filename = input("(You want to get)>>>:").strip()
16     if filename == '#exit':
17         break
18     client.send(filename.encode('utf-8'))
19 
20     file_size = client.recv(1024).decode()
21     if file_size.isdigit():
22         '''文件大小是不小于0的数字,则文件存在,准备接收'''
23         file_size = int(file_size)
24         if file_size >= 0:
25             data_size = 0
26             data_md5 = hashlib.md5()         #初始化MD5对象,用以向服务端校验
27             client.send("OK".encode('utf-8'))         #向服务端确认接收数据
28             with open(filename, 'wb') as fp:
29                 while data_size < file_size:
30                     data = client.recv(1024)
31                     data_md5.update(data)
32                     data_size += len(data)
33                     fp.write(data)
34             client.send(data_md5.hexdigest().encode('utf-8'))    #发送服务端发送数据的MD5码
35             message = client.recv(1024).decode()           #接收并打印服务端的校验信息
36             print(message)
37             print('\n\n\n')
38     else :
39         '''文件大小不是数字,则出错,打印服务端的提示信息'''
40         print(file_size)
41         continue
42 
43 client.close()
ftp_socket_client

     注意:如果代码中有两个(或两个以上)socket.send()连在一起(中间无阻塞(比如time.slee(), socket.recv()等)),有粘包风险。

 


通过上面的代码编写,可以发现尽管socket已经简化了网络编程的过程,但还是给人一种面向过程的感觉。记下来的socketserver便解决了网络服务端编程过于繁琐的问题。

socketserver:

socketserver模块简化了编写网络服务器的任务。

有四个基本的具体服务器类:

class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)

这使用Internet TCP协议,它在客户端和服务器之间提供连续的数据流。如果bind_and_activate为true,构造函数将自动尝试调用server_bind()server_activate()其他参数传递到BaseServer基类。

class socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)

这使用数据报,其是可能在运输中不按顺序到达或丢失的信息的离散分组。参数与TCPServer相同。

class socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
class socketserver.UnixDatagramServer(server_address, RequestHandlerClass, bind_and_activate=True)

这些更常用的类与TCP和UDP类类似,但使用Unix域套接字;它们在非Unix平台上不可用。参数与TCPServer相同。

这四个类同时处理请求;每个请求必须在下一个请求开始之前完成。如果每个请求需要很长时间来完成,这是不合适的,因为它需要大量的计算,或者因为它返回了很多客户端处理速度慢的数据。解决方案是创建一个单独的进程或线程来处理每个请求; ForkingMixInThreadingMixIn混合类可以用于支持异步行为。

创建服务器需要几个步骤。首先,您必须通过对BaseRequestHandler类进行子类化并覆盖其handle()方法来创建请求处理程序类;此方法将处理传入请求。其次,您必须实例化一个服务器类,将它传递给服务器的地址和请求处理程序类。然后调用服务器对象的handle_request()serve_forever()方法来处理一个或多个请求。最后,调用server_close()关闭套接字。

当从ThreadingMixIn继承线程连接行为时,应该明确声明您希望线程在突然关闭时的行为。ThreadingMixIn类定义了一个属性daemon_threads,它指示服务器是否应该等待线程终止。如果您希望线程自主行为,您应该明确地设置标志;默认值为False,这意味着Python不会退出,直到ThreadingMixIn创建的所有线程都退出。

#四个基本类的继承关系
+------------+ | BaseServer | +------------+ | v +-----------+ +------------------+ | TCPServer |------->| UnixStreamServer | +-----------+ +------------------+ | v +-----------+ +--------------------+ | UDPServer |------->| UnixDatagramServer | +-----------+ +--------------------+

  例五(我们使用socketserver实现例二):

 

 1 import socketserver
 2 
 3 class MyTCPRequestHandler(socketserver.BaseRequestHandler):
 4     """
 5     The request handler class for our server.
 6 
 7     It is instantiated once per connection to the server, and must
 8     override the handle() method to implement communication to the
 9     client.
10     """
11     def handle(self):
12         """
13         服务端和客户端连接后,数据的交互由这个方法实现,这个方法必须重写
14         """
15         while True:
16             try:
17                 self.data = self.request.recv(1024).strip()
18                 print("server recv:", self.data.decode())
19                 self.request.send(self.data.upper())
20             except ConnectionResetError:
21                 break
22 
23 if __name__ == "__main__":
24     HOST, PORT = "localhost", 6666
25     server = socketserver.TCPServer((HOST, PORT), MyTCPRequestHandler)    
26     server.serve_forever()            #处理请求
27     server.server_close()             #关闭套接字
TCPSever

 

     注:服务器类具有相同的外部方法和属性,无论它们使用什么网络协议。

  例六(使用ThreadingMixIn可以轻松实现一对多同时服务(多线程)):

 1 import socketserver
 2 
 3 class MyTCPRequestHandler(socketserver.BaseRequestHandler):
 4     """
 5     The request handler class for our server.
 6 
 7     It is instantiated once per connection to the server, and must
 8     override the handle() method to implement communication to the
 9     client.
10     """
11     def handle(self):
12         """
13         服务端和客户端连接后,数据的交互由这个方法实现,这个方法必须重写
14         """
15         while True:
16             try:
17                 self.data = self.request.recv(1024).strip()
18                 print("server recv:", self.data.decode())
19                 self.request.send(self.data.upper())
20             except ConnectionResetError:
21                 break
22 
23 if __name__ == "__main__":
24     HOST, PORT = "localhost", 6666
25     server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPRequestHandler)    #同时处理多个连接
26     server.serve_forever()            #处理请求
27     server.server_close()             #关闭套接字
28 
29 
30 
31 
32 #ThreadingTCPServer的源码
33 '''
34 class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
35 '''
ThreadingTCPServer

                   注:其他协议的多线程实现同上。

                  PS(本例中所涉及到的模块使用参考):

          socket模块:http://www.cnblogs.com/God-Li/p/7625825.html

          hashlib模块:http://www.cnblogs.com/God-Li/p/7631604.html

          os模块:http://www.cnblogs.com/God-Li/p/7384227.html

          socketserver模块:http://python.usyiyi.cn/translate/python_352/library/socketserver.html#module-socketserver

目录
相关文章
|
6天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【蘑菇识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
蘑菇识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了9种常见的蘑菇种类数据集【"香菇(Agaricus)", "毒鹅膏菌(Amanita)", "牛肝菌(Boletus)", "网状菌(Cortinarius)", "毒镰孢(Entoloma)", "湿孢菌(Hygrocybe)", "乳菇(Lactarius)", "红菇(Russula)", "松茸(Suillus)"】 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,
45 11
基于Python深度学习的【蘑菇识别】系统~卷积神经网络+TensorFlow+图像识别+人工智能
|
25天前
|
安全 Linux 网络安全
利用Python脚本自动备份网络设备配置
通过本文的介绍,我们了解了如何利用Python脚本自动备份网络设备配置。该脚本使用 `paramiko`库通过SSH连接到设备,获取并保存配置文件。通过定时任务调度,可以实现定期自动备份,确保网络设备配置的安全和可用。希望这些内容能够帮助你在实际工作中实现网络设备的自动化备份。
51 14
|
1月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
133 5
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
2月前
|
算法 网络协议 Python
探秘Win11共享文件夹之Python网络通信算法实现
本文探讨了Win11共享文件夹背后的网络通信算法,重点介绍基于TCP的文件传输机制,并提供Python代码示例。Win11共享文件夹利用SMB协议实现局域网内的文件共享,通过TCP协议确保文件传输的完整性和可靠性。服务器端监听客户端连接请求,接收文件请求并分块发送文件内容;客户端则连接服务器、接收数据并保存为本地文件。文中通过Python代码详细展示了这一过程,帮助读者理解并优化文件共享系统。
|
2月前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
355 55
|
2月前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
220 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
2月前
|
机器学习/深度学习 人工智能 算法
深度学习入门:用Python构建你的第一个神经网络
在人工智能的海洋中,深度学习是那艘能够带你远航的船。本文将作为你的航标,引导你搭建第一个神经网络模型,让你领略深度学习的魅力。通过简单直观的语言和实例,我们将一起探索隐藏在数据背后的模式,体验从零开始创造智能系统的快感。准备好了吗?让我们启航吧!
115 3
|
3月前
|
网络安全 Python
Python网络编程小示例:生成CIDR表示的IP地址范围
本文介绍了如何使用Python生成CIDR表示的IP地址范围,通过解析CIDR字符串,将其转换为二进制形式,应用子网掩码,最终生成该CIDR块内所有可用的IP地址列表。示例代码利用了Python的`ipaddress`模块,展示了从指定CIDR表达式中提取所有IP地址的过程。
91 6
|
3月前
|
数据采集 XML 存储
构建高效的Python网络爬虫:从入门到实践
本文旨在通过深入浅出的方式,引导读者从零开始构建一个高效的Python网络爬虫。我们将探索爬虫的基本原理、核心组件以及如何利用Python的强大库进行数据抓取和处理。文章不仅提供理论指导,还结合实战案例,让读者能够快速掌握爬虫技术,并应用于实际项目中。无论你是编程新手还是有一定基础的开发者,都能在这篇文章中找到有价值的内容。
|
3月前
|
机器学习/深度学习 自然语言处理 语音技术
Python在深度学习领域的应用,重点讲解了神经网络的基础概念、基本结构、训练过程及优化技巧
本文介绍了Python在深度学习领域的应用,重点讲解了神经网络的基础概念、基本结构、训练过程及优化技巧,并通过TensorFlow和PyTorch等库展示了实现神经网络的具体示例,涵盖图像识别、语音识别等多个应用场景。
112 8

热门文章

最新文章

推荐镜像

更多