建设网站收取广告费用网页升级紧急通知app下载
建设网站收取广告费用,网页升级紧急通知app下载,山西推广型网站制作,销售行业怎样做网站推荐#xff1a;使用 NSDT场景编辑器 快速搭建3D应用场景 连接设备以交换信息是网络的全部意义所在。套接字是有效网络通信的重要组成部分#xff0c;因为它们是用于通过本地或全球网络以及同一台计算机上的不同进程在设备之间传输消息的基本概念。它们提供了一个低级接口使用 NSDT场景编辑器 快速搭建3D应用场景 连接设备以交换信息是网络的全部意义所在。套接字是有效网络通信的重要组成部分因为它们是用于通过本地或全球网络以及同一台计算机上的不同进程在设备之间传输消息的基本概念。它们提供了一个低级接口允许对要发送或接收的流量进行细粒度控制。
这种低级特性使得可以为特定用例创建性能非常高的通信通道或自定义协议这些用例可能存在于传统协议中这些协议建立在套接字通信之上。
这就是套接字在依赖即时消息交换或处理大量数据的实时客户端-服务器应用程序中非常有用的原因。
在本文中我们将介绍套接字编程的基础知识并提供使用 Python 创建基于套接字的客户端和服务器应用程序的分步指南。因此事不宜迟让我们直接潜入
网络基础知识
网络支持任何类型的通信和信息共享。
这是连接两个或多个设备以允许它们交换信息的过程。此类互连设备的集合称为网络。
我们可以在物理世界中观察到许多网络航空公司或电力线网络或通过高速公路相互连接的城市就是一些很好的例子。
同样信息技术领域有许多网络;其中最突出和最著名的是互联网这是连接无数设备的全球网络网络也是您现在可能正在使用的阅读本文的网络。
网络类型
互联网包含更多的网络这些网络本身因规模或其他属性而异例如局域网 LAN它们通常将彼此靠近的计算机链接起来。公司或其他机构银行、大学等中的机器甚至连接到路由器的家庭设备都构成了这样的网络。
还有更大或更小类型的网络如PAN个人局域网可以简单地将您的智能手机通过蓝牙连接到笔记本电脑MAN城域网可以互连整个城市的设备以及WAN广域网可以覆盖整个国家或整个世界。是的最大的WAN网络是互联网本身。
不言而喻计算机网络可能非常复杂由许多元素组成。最基本和最关键的原语之一是通信协议。
网络通信协议的类型
通信协议规定了如何以及以何种格式发送和接收信息的规则。这些协议被组装到一个层次结构中以管理网络通信中涉及的各种任务。
换句话说一些协议处理硬件接收、发送或路由数据包的方式而其他协议则更高级别例如关注应用程序级通信等。
一些常用和广为人知的网络通信协议包括
无线网络
链路层协议的示例这意味着它非常靠近硬件并负责在无线环境中将数据从一台设备物理发送到另一台设备。
IP互联网协议
IP 是一种网络层协议主要负责路由数据包和 IP 寻址。
TCP传输控制协议
一种可靠的、面向连接的协议可提供全双工通信并确保数据完整性和交付。这是一种传输层协议用于管理连接、检测错误和控制信息流。
UDP用户数据报协议
与 TCP 来自同一协议套件的协议。主要区别在于 UDP 是一种更简单、更快速但不可靠的无连接协议它不执行任何传递检查并遵循“即发即弃”的范式。作为TCPUPD也位于传输层。
HTTP超文本传输协议
一种应用层协议也是网络上浏览器到服务器通信最常用的协议特别用于为网站提供服务。不用说您现在正在阅读的这篇文章也是通过HTTP提供的。HTTP协议建立在TCP之上管理和传输与Web应用程序相关的信息如用于传输元数据和cookie的标头不同的HTTP方法GETPOSTDELETEUPDATE等。
MQTT消息队列遥测传输
另一个应用程序级协议示例用于处理能力和电池寿命有限的设备在不可靠的网络条件下运行例如采矿现场的气体传感器或您家中的智能灯泡。MQTT是IoT物联网中使用的标准消息传递协议。它既轻巧又易于使用设计有内置的重传机制可增强可靠性。如果您有兴趣将此协议与 Python 一起使用可以阅读此 Python MQTT 指南其中提供了 Paho MQTT 客户端的深入概述。
一个重要的观察结果是上述所有协议都在引擎盖下使用套接字但在顶部添加了自己的逻辑和数据处理。这是由于套接字是现代设备中任何网络通信的低级接口我们将在下一节中讨论。
关键概念和术语
当然在网络环境中还使用了许多其他重要概念和术语。以下是本教程其余部分可能出现的一些最突出问题的快速概述
数据包计算机网络中数据传输的标准单位可以通俗地将其与术语“消息”进行比较。终结点数据包到达的目标。IP 地址唯一标识网络上设备的数字标识符。IP 地址的示例为192.168.0.0端口一个数字标识符用于唯一标识设备上运行的进程并处理特定的网络通信例如它通过HTTP为您的网站提供服务。IP 地址标识设备端口标识应用程序每个应用程序都是一个进程或由进程组成。一些众所周知的端口示例是端口 80服务器应用程序通常使用它来管理 HTTP 流量以及端口 443 用于 HTTPS安全 HTTP。网关一种特殊的网络节点设备用作从一个网络到另一个网络的接入点。这些网络甚至可能使用不同的协议因此网关可能需要执行一些协议转换。网关的一个例子可以是将家庭本地网络连接到互联网的路由器。
了解套接字
什么是套接字
套接字是位于相同或不同机器上的不同进程之间进行通信的接口门。在后一种情况下我们谈论网络套接字。
网络套接字抽象出连接管理。您可以将它们视为连接处理程序。特别是在Unix系统中套接字只是支持相同写读操作但通过网络发送所有数据的文件。
当套接字处于侦听或连接状态时它始终绑定到 IP 地址和标识主机计算机/设备和进程的端口号的组合。
套接字连接的工作原理
套接字可以侦听传入连接或自行执行出站连接。建立连接后侦听套接字服务器套接字将额外绑定到连接端的 IP 和端口。
或者创建一个新的套接字该套接字现在绑定到侦听器和请求者的两对 IP 地址和端口号。这样不同计算机上的两个连接的套接字可以相互识别并共享单个连接以进行数据传输而不会阻塞侦听套接字同时侦听套接字会继续侦听其他连接。
对于连接套接字客户端套接字它会在连接启动时隐式绑定到设备的 IP 地址和随机可访问的端口号。然后在建立连接时与另一通信端的 IP 和端口的绑定方式与侦听套接字大致相同但不创建新套接字。
网络上下文中的套接字
在本教程中我们关注的不是套接字实现而是套接字在网络上下文中的含义。
可以说套接字是一个连接端点流量目的地它一方面与主机的 IP 地址和为其创建套接字的应用程序的端口号相关联另一方面它与在建立连接的另一台计算机上运行的应用程序的 IP 地址和端口相关联。
套接字编程
当我们谈论套接字编程时我们在代码中实例化套接字对象并对其执行操作侦听、连接、接收、发送等。在这种情况下套接字只是我们在程序中创建的特殊对象它们具有处理网络连接和流量的特殊方法。
在后台这些方法调用操作系统内核或者更具体地说调用网络堆栈网络堆栈是内核中负责管理网络操作的特殊部分。
套接字和客户端-服务器通信
现在同样重要的是要提到套接字经常出现在客户端-服务器通信的上下文中。
这个想法很简单套接字与连接有关;它们是连接处理程序。在 Web 上每当您想要发送或接收一些数据时您都会启动一个连接通过称为套接字的接口启动。
现在您或您尝试连接的一方充当服务器另一方充当客户端。当服务器向客户端提供数据时客户端会主动连接并从服务器请求数据。服务器通过侦听套接字侦听新连接建立新连接获取客户端的请求并在响应中将请求的数据传达给客户端。
另一方面客户端使用它希望连接的服务器的 IP 地址和端口创建套接字启动连接将其请求传达给服务器并接收数据作为响应。客户端和服务器套接字之间的这种无缝信息交换构成了各种网络应用程序的骨干。
套接字作为网络协议的基础
套接字形成骨干的事实也意味着在其上构建和使用各种协议。非常常见的是UDP和TCP我们已经简要讨论过了。使用这些传输协议之一的套接字称为 UDP 或 TCP 套接字。
工控机插座
除了网络套接字还有其他类型。例如IPC进程间通信套接字。IPC 套接字用于在同一台计算机上的进程之间传输数据而网络套接字可以在网络上执行相同的操作。
IPC 套接字的好处是它们避免了构建数据包和解析发送数据的路由的大量开销。由于在IPC发送方和接收方的上下文中是本地进程因此通过IPC套接字进行通信通常具有较低的延迟。
Unix-sockets
IPC套接字的一个很好的例子是Unix套接字与Unix中的所有内容一样它只是文件系统上的文件。它们不是由 IP 地址和端口标识而是由文件系统上的文件路径标识。
网络套接字作为 IPC 套接字
请注意如果服务器和接收方都在本地主机上即具有 IP 地址 127.0.0.1您也可以使用网络套接字进行进程间通信。
当然一方面由于与网络堆栈处理数据相关的开销这会增加额外的延迟但另一方面这使我们能够不必担心底层操作系统因为网络套接字存在并在所有系统上工作而不是特定于给定操作系统或操作系统系列的 IPC 套接字。
Python 套接字库
对于 Python 中的套接字编程我们使用官方内置的 Python 套接字库该库由用于创建、管理和使用套接字的函数、常量和类组成。此库的一些常用功能包括
socket创建一个新套接字。bind将套接字关联到特定地址和端口。listen开始侦听套接字上的传入连接。accept接受来自客户端的连接并返回用于通信的新套接字。connect建立与远程服务器的连接。send通过套接字发送数据。recv从套接字接收数据。close关闭套接字连接。
Python 套接字示例
让我们通过一个用 Python 编写的实际示例来了解套接字编程。在这里我们的目标是连接两个应用程序并使它们相互通信。我们将使用 Python 套接字库创建一个服务器套接字应用程序该应用程序将通过网络与客户端进行通信和交换信息。
注意事项和限制
但是请注意出于教育目的我们的示例进行了简化应用程序将在本地运行而不是通过实际网络进行通信 - 我们将使用环回本地主机地址将客户端连接到服务器。
这意味着客户端和服务器将在同一台计算机上运行并且客户端将启动与运行它的同一台计算机的连接尽管连接到表示服务器的不同进程。
在不同的计算机上运行
或者您可以将应用程序放在两个不同的设备上并将它们都连接到同一个Wi-Fi路由器这将形成局域网。然后在一台设备上运行的客户端可以连接到在另一台计算机上运行的服务器。
但是在这种情况下您需要知道路由器分配给设备的IP地址并使用它们而不是本地主机127.0.0.1环回IP地址要查看IP地址请使用终端命令用于类Unix系统或-对于Windows。获取应用程序的 IP 地址后可以在代码中相应地更改它们该示例仍然有效。ifconfigipconfig
无论如何我们将从我们的例子开始。当然如果你想跟上去你需要安装Python。
在 Python 中创建套接字服务器
让我们从创建一个套接字服务器特别是Python TCP服务器因为它将与TCP套接字一起工作正如我们将看到的它将与客户端交换消息。为了澄清术语虽然从技术上讲任何服务器都是套接字服务器但由于套接字总是在后台使用来启动网络连接因此我们使用短语“套接字服务器”因为我们的示例明确使用了套接字编程。
因此请按照以下步骤操作
使用一些样板创建 python 文件
创建一个名为server.py在 Python 脚本中导入模块。socket 添加一个名为 的函数。我们将在那里添加大部分代码。将代码添加到函数时不要忘记正确缩进它run_server 实例化套接字对象
下一步在 中使用该函数创建一个套接字对象。run_serversocket.socket()
第一个参数 指定 IPv4 的 IP 地址系列其他选项包括IPv6 系列和 Unix 套接字socket.AF_INETAF_INET6AF_UNIX
第二个参数表示我们正在使用TCP套接字。socket.SOCK_STREAM)
在使用TCP的情况下操作系统将通过顺序数据传输错误发现和重新传输以及流量控制创建可靠的连接。您不必考虑实现所有这些细节。
还有一个用于指定 UDP 套接字的选项。这将创建一个套接字该套接字在后台实现UDP的所有功能。socket.SOCK_DGRAM
如果你想更底层并在套接字使用的TCP/IP网络层协议之上构建自己的传输层协议你可以使用value作为第二个参数。在这种情况下操作系统将不会为您处理任何更高级别的协议功能如果需要您必须自己实现所有标头、连接确认和重传功能。您还可以在文档中阅读其他值。socket.RAW_SOCKET 将服务器套接字绑定到 IP 地址和端口
定义主机名或服务器 IP 和端口以指示服务器可从何处访问以及侦听传入连接的位置。在此示例中服务器正在侦听本地计算机 - 这是由设置为 也称为 localhost 的变量定义的。server_ip127.0.0.1
该变量设置为 这是操作系统将标识服务器应用程序的端口号建议对端口号使用大于 1023 的值以避免与系统进程使用的端口发生冲突。port8000 通过将套接字绑定到我们之前定义的 IP 地址和端口来准备套接字以接收连接。 侦听传入连接
使用该函数在服务器套接字中设置侦听状态以便能够接收传入的客户端连接。listen
此函数接受调用的参数该参数指定排队的未接受连接的最大数量。在此示例中我们使用此参数的值。这意味着只有一个客户端可以与服务器交互。在服务器使用另一个客户端时执行的任何客户端的连接尝试都将被拒绝。backlog0
如果指定的值大于 例如它会告诉操作系统在对客户端调用方法之前可以放入队列中的客户端数。01accept
调用一次客户端将从队列中删除不再计入此限制。一旦您看到代码的更多部分这可能会变得更加清晰但此参数本质上的作用可以说明如下一旦您的侦听服务器收到连接请求它将将此客户端添加到队列中并继续接受它的请求。如果在服务器能够在第一个客户端上进行内部调用之前它收到来自第二个客户端的连接请求则只要其中有足够的空间它将把第二个客户端推送到同一队列。此队列的大小由积压工作参数控制。一旦服务器接受第一个客户端该客户端就会从队列中删除服务器开始与其通信。第二个客户端仍留在队列中等待服务器获得空闲并接受连接。acceptaccept
如果省略 backlog 参数它将设置为系统的默认值在 Unix 下您通常可以在文件中查看此默认值。/proc/sys/net/core/somaxconn 接受传入连接
接下来等待并接受传入的客户端连接。该方法将停止执行线程直到客户端连接。然后它返回一个元组对其中地址是客户端 IP 地址和端口的元组并且是与客户端共享连接并可用于与其通信的新套接字对象。accept(conn, address)conn
accept创建一个新的套接字来与客户端通信而不是将侦听套接字在我们的示例中称为绑定到客户端的地址并将其用于通信因为侦听套接字需要侦听来自其他客户端的进一步连接否则它将被阻止。当然在我们的例子中我们只处理一个客户端并在这样做时拒绝所有其他连接但是一旦我们进入多线程服务器示例这将更加相关。server 创建通信循环
一旦与客户端建立了连接在调用方法之后我们就会启动一个无限循环进行通信。在此循环中我们对对象的方法执行调用。此方法从客户端接收指定数量的字节 - 在我们的例子中为 1024。acceptrecvclient_socket
1024 字节只是有效负载大小的常见约定因为它是 的幂可能比其他任意值更适合优化目的。您可以随意更改此值。
由于从客户端接收到变量中的数据是原始二进制形式因此我们使用该函数将其从字节序列转换为字符串。requestdecode
然后我们有一个 if 语句如果我们收到消息它会脱离通信循环。这意味着一旦我们的服务器在请求中收到字符串它就会将确认发送回客户端并终止与客户端的连接。否则我们将收到的消息打印到控制台。在我们的例子中确认只是向客户端发送一个字符串。”close””close””closed”
请注意我们在 if 语句中的字符串上使用的方法只是将其转换为小写。这样我们就不在乎字符串最初是使用大写还是小写字符编写的。lowerrequestclose 将响应发送回客户端
现在我们应该处理服务器对客户端的正常响应即当客户端不希望关闭连接时。在 while 循环中紧接着 添加以下行这会将响应字符串在我们的例子中转换为字节并将其发送到客户端。这样每当服务器收到来自客户端的消息时它将发送字符串作为响应print(fReceived: {request})”accepted””close””accepted” 释放资源
一旦我们脱离了无限 while 循环与客户端的通信就完成了所以我们使用释放系统资源的方法关闭客户端套接字。我们还使用相同的方法关闭服务器套接字这有效地关闭了我们的服务器。在现实世界中我们当然可能希望我们的服务器继续侦听其他客户端而不是在与单个客户端通信后关闭但别担心我们将在下面进一步介绍另一个示例。close
现在在无限 while 循环之后添加以下行 注意不要忘记在文件末尾调用该函数。只需使用以下代码行run_serverserver.py 完整的服务器套接字代码示例
以下是完整的源代码server.py
import socket
def run_server(): # create a socket object server socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_ip 127.0.0.1
port 8000# bind the socket to a specific address and port
server.bind((server_ip, port))
# listen for incoming connections
server.listen(0)
print(fListening on {server_ip}:{port})# accept incoming connections
client_socket, client_address server.accept()
print(fAccepted connection from {client_address[0]}:{client_address[1]})# receive data from the client
while True:request client_socket.recv(1024)request request.decode(utf-8) # convert bytes to string# if we receive close from the client, then we break# out of the loop and close the connecitonif request.lower() close:# send response to the client which acknowledges that the# connection should be closed and break out of the loopclient_socket.send(closed.encode(utf-8))breakprint(fReceived: {request})response accepted.encode(utf-8) # convert string to bytes# convert and send accept response to the clientclient_socket.send(response)# close connection socket with the client
client_socket.close()
print(Connection to client closed)
# close server socket
server.close()run_server()
请注意为了不使这个基本示例复杂化和复杂化我们省略了错误处理。您当然希望添加 try-except 块并确保始终关闭子句中的套接字。继续阅读我们将看到一个更高级的示例。finally
在 Python 中创建客户端套接字
设置服务器后下一步是设置一个客户端该客户端将连接并向服务器发送请求。因此让我们从以下步骤开始
使用一些样板创建 python 文件
创建一个名为client.py导入套接字库
import socket
定义我们将放置所有代码的函数run_client
def run_client(): # your code will go here
实例化套接字对象
接下来使用该函数创建一个 TCP 套接字对象该对象充当客户端与服务器的联系点。socket.socket()
// create a socket object client socket.socket(socket.AF_INET, socket.SOCK_STREAM)
连接到服务器套接字
指定服务器的 IP 地址和端口以便能够连接到它。这些地址和端口应与您之前设置的 IP 地址和端口匹配。server.py
server_ip 127.0.0.1 # replace with the servers IP address
server_port 8000 # replace with the servers port number使用客户端套接字对象上的方法与服务器建立连接。请注意我们没有将客户端套接字绑定到任何 IP 地址或端口。这对客户端来说是正常的因为将自动选择一个空闲端口并选取一个 IP 地址该地址从系统的网络接口在我们的例子中提供到服务器的最佳路由并将客户端套接字绑定到这些接口。connectconnect127.0.0.1
# establish connection with server
client.connect((server_ip, server_port))创建通信循环
建立连接后我们开始无限通信循环以向服务器发送多条消息。我们使用 Python 的内置函数从用户那里获取输入然后将其编码为字节并修剪为最大 1024 字节。之后我们使用.inputclient.send
while True: # input message and send it to the server msg input(Enter message: ) client.send(msg.encode(utf-8)[:1024])
处理服务器的响应
一旦服务器收到来自客户端的消息它就会响应它。现在在我们的客户端代码中我们希望接收服务器的响应。为此在通信循环中我们使用该方法最多读取 1024 字节。然后我们使用将字节的响应转换为字符串然后检查它是否等于值。如果是这种情况我们将脱离循环正如我们稍后看到的这将终止客户端的连接。否则我们将服务器的响应打印到控制台中。recvdecode”closed” # receive message from the serverresponse client.recv(1024)response response.decode(utf-8)# if server sent us closed in the payload, we break out of the loop and close our socketif response.lower() closed:breakprint(fReceived: {response})释放资源
最后在 while 循环之后使用该方法关闭客户端套接字连接。这可确保正确释放资源并终止连接即当我们收到消息并脱离 while 循环时。close“closed”
// close client socket (connection to the server) client.close() print(Connection to server closed)
注意同样不要忘记在文件末尾调用我们上面实现的函数如下所示run_client
run_client()
完整的客户端套接字代码示例
以下是完整的代码client.py
import socket
def run_client(): # create a socket object client socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_ip 127.0.0.1 # replace with the servers IP address
server_port 8000 # replace with the servers port number
# establish connection with server
client.connect((server_ip, server_port))while True:# input message and send it to the servermsg input(Enter message: )client.send(msg.encode(utf-8)[:1024])# receive message from the serverresponse client.recv(1024)response response.decode(utf-8)# if server sent us closed in the payload, we break out of the loop and close our socketif response.lower() closed:breakprint(fReceived: {response})# close client socket (connection to the server)
client.close()
print(Connection to server closed)run_client()
测试客户端和服务器
要测试我们上面编写的服务器和客户端实现请执行以下操作
同时打开两个终端窗口。在一个终端窗口中导航到文件所在的目录然后运行以下命令以启动服务器server.py
python server.py
这会将服务器套接字绑定到端口 127 上的本地主机地址 0.0.1.8000并开始侦听传入连接。
在另一个终端中导航到文件所在的目录并运行以下命令以启动客户端client.py
python client.py
这将提示用户输入。然后您可以键入消息并按 Enter 键。这会将您的输入传输到服务器并在其终端窗口中显示。服务器将向客户端发送响应后者将再次要求您输入。这将一直持续到您将字符串发送到服务器。”close”
使用多个客户端 – 多线程
我们已经在前面的示例中看到了服务器如何响应来自单个客户端的请求但是在许多实际情况中许多客户端可能需要同时连接到单个服务器。这就是多线程的用武之地。多线程用于需要同时同时处理多个任务例如执行多个功能的情况。
这个想法是生成一个线程该线程是一组独立的指令可以由处理器处理。线程比进程轻量级得多因为它们实际上存在于进程本身中您不必为自己分配大量资源。
python中多线程的局限性
请注意Python 中的多线程是有限的。标准的Python实现CPython不能真正并行运行线程。由于全局解释器锁 GIL一次只允许执行一个线程。但是这是一个单独的主题我们不打算讨论。为了我们的示例使用有限的CPython线程就足够了并且可以理解这一点。但是在实际场景中如果您要使用Python则应研究异步编程。我们现在不打算讨论它因为它又是一个单独的主题它通常会抽象出一些我们在本文中特别关注的低级套接字操作。
多线程服务器示例
让我们看一下下面的示例了解如何将多线程添加到服务器中以处理大量客户端。请注意这次我们还将使用 try-except-finally 块添加一些基本的错误处理。要开始使用请按照以下步骤操作
创建线程生成服务器函数
在您的 python 文件中导入 and 模块以便能够同时使用套接字和线程
定义函数如上例所示创建一个服务器套接字绑定它并侦听传入的连接。然后调用无限 while 循环。这将始终侦听新的连接。获取传入连接并返回后使用构造函数创建一个线程。该线程将执行我们稍后将要定义的函数并作为参数传递给它元组包含所连接客户端的 IP 地址和端口。创建线程后我们调用它开始执行。run_serveracceptacceptthreading.Threadhandle_clientclient_socketaddraddrstart
请记住调用是阻塞的因此在 while 循环的第一次迭代中当我们到达 的行时我们停止并等待客户端连接而不执行任何其他操作。一旦客户端连接方法就会返回我们继续执行生成一个线程该线程将处理所述客户端并转到下一次迭代我们将再次在调用处停止等待另一个客户端连接。acceptacceptacceptaccept
在函数结束时我们有一些错误处理以确保服务器套接字始终关闭以防发生意外情况。
def run_server(): server_ip 127.0.0.1 # server hostname or IP address port 8000 # server port number # create a socket object try: server socket.socket(socket.AF_INET, socket.SOCK_STREAM) # bind the socket to the host and port server.bind((server_ip, port)) # listen for incoming connections server.listen() print(fListening on {server_ip}:{port}) while True:# accept a client connectionclient_socket, addr server.accept()print(fAccepted connection from {addr[0]}:{addr[1]})# start a new thread to handle the clientthread threading.Thread(targethandle_client, args(client_socket, addr,))thread.start()
except Exception as e:print(fError: {e})
finally:server.close()请注意我们示例中的服务器仅在发生意外错误时才会停止。否则它将无限期地侦听客户端如果要停止它则必须杀死终端。
创建客户端处理函数以在单独的线程中运行
现在在函数上方定义另一个名为 .此函数将是在每个客户端连接的单独线程中执行的函数。它接收客户端的套接字对象和元组作为参数。run_serverhandle_clientaddr
在这个函数中我们执行与单线程示例中相同的操作以及一些错误处理我们启动一个循环以使用 .recv
然后我们检查我们是否收到关闭的消息。如果是这样我们使用字符串响应并通过中断循环来关闭连接。否则我们将客户端的请求字符串打印到控制台中然后继续进行下一个循环迭代以接收下一个客户端的消息。”closed”
在这个函数的末尾我们有一些针对意外情况的错误处理子句还有一个使用.无论如何此子句将始终执行这可确保始终正确释放客户端套接字。
def handle_client(client_socket, addr): try: while True: # receive and print client messages request client_socket.recv(1024).decode(utf-8) if request.lower() close: client_socket.send(closed.encode(utf-8)) break print(fReceived: {request}) # convert and send accept response to the client response accepted client_socket.send(response.encode(utf-8)) except Exception as e: print(fError when hanlding client: {e}) finally: client_socket.close() print(fConnection to client ({addr[0]}:{addr[1]}) closed)
当返回时执行它的线程也将自动释放。handle_client
注意不要忘记在文件末尾调用该函数。run_server
完整的多线程服务器代码示例
现在让我们把完整的多线程服务器代码放在一起
import socket import threading
def handle_client(client_socket, addr): try: while True: # receive and print client messages request client_socket.recv(1024).decode(utf-8) if request.lower() close: client_socket.send(closed.encode(utf-8)) break print(fReceived: {request}) # convert and send accept response to the client response accepted client_socket.send(response.encode(utf-8)) except Exception as e: print(fError when hanlding client: {e}) finally: client_socket.close() print(fConnection to client ({addr[0]}:{addr[1]}) closed)
def run_server(): server_ip 127.0.0.1 # server hostname or IP address port 8000 # server port number # create a socket object try: server socket.socket(socket.AF_INET, socket.SOCK_STREAM) # bind the socket to the host and port server.bind((server_ip, port)) # listen for incoming connections server.listen() print(fListening on {server_ip}:{port}) while True:# accept a client connectionclient_socket, addr server.accept()print(fAccepted connection from {addr[0]}:{addr[1]})# start a new thread to handle the clientthread threading.Thread(targethandle_client, args(client_socket, addr,))thread.start()
except Exception as e:print(fError: {e})
finally:server.close()run_server()
注意在实际代码中为了防止在处理多线程服务器时出现争用情况或数据不一致等可能的问题必须考虑线程安全和同步技术。然而在我们的简单示例中这不是问题。
具有基本错误处理的客户端示例
现在我们有一个能够同时处理多个客户端的服务器实现我们可以使用上面第一个基本示例中所示的相同客户端实现来启动连接或者我们可以稍微更新它并添加一些错误处理。您可以在下面找到代码该代码与前面的客户端示例相同但添加了 try-except 块
import socket
def run_client(): # create a socket object client socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_ip 127.0.0.1 # replace with the servers IP address
server_port 8000 # replace with the servers port number
# establish connection with server
client.connect((server_ip, server_port))try:while True:# get input message from user and send it to the servermsg input(Enter message: )client.send(msg.encode(utf-8)[:1024])# receive message from the serverresponse client.recv(1024)response response.decode(utf-8)# if server sent us closed in the payload, we break out of# the loop and close our socketif response.lower() closed:breakprint(fReceived: {response})
except Exception as e:print(fError: {e})
finally:# close client socket (connection to the server)client.close()print(Connection to server closed)run_client()
测试多线程示例
如果要测试多客户端实现请为客户端打开多个终端窗口为服务器打开一个终端窗口。首先使用 启动服务器。之后使用 .在服务器终端窗口中您将看到新客户端如何连接到服务器。现在您可以通过在相应的终端中输入文本来继续从不同的客户端发送消息所有这些消息都将被处理并打印到服务器端的控制台。python server.pypython client.py
套接字编程在数据科学中的应用
虽然每个网络应用程序都使用操作系统在后台创建的套接字但有许多系统严重依赖套接字编程无论是用于某些特殊用例还是为了提高性能。但是套接字编程在数据科学的背景下究竟有什么用呢嗯每当需要快速接收或发送大量数据时它肯定起着有意义的作用。因此套接字编程主要用于数据收集和实时处理、分布式计算和进程间通信。但是让我们仔细看看数据科学领域的一些特定应用。
实时数据收集
套接字广泛用于从不同来源收集实时数据以进行进一步处理、转发到数据库或分析管道等。例如套接字可用于从金融系统或社交媒体API即时接收数据以供数据科学家进行后续处理。
分布式计算
数据科学家可以使用套接字连接在多台机器上分配大型数据集的处理和计算。套接字编程通常用于Apache Spark和其他分布式计算框架中用于节点之间的通信。
模型部署
在向用户提供机器学习模型时可以使用套接字编程从而即时提供预测和建议。为了促进实时决策数据科学家可以使用基于套接字的高性能服务器应用程序这些应用程序接收大量数据使用经过训练的模型对其进行处理以提供预测然后将结果快速返回给客户端。
进程间通信 IPC
套接字可用于IPC它允许在同一台机器上运行的不同进程相互通信并交换数据。这在数据科学中很有用可以在多个进程中分配复杂和资源密集型计算。事实上Python 的子处理库经常用于此目的它生成多个进程以利用多个处理器内核并在执行繁重计算时提高应用程序性能。此类进程之间的通信可以通过IPC套接字实现。
协作与沟通
套接字编程允许数据科学家之间的实时通信和协作。为了促进有效的协作和知识共享使用了基于套接字的聊天应用程序或协作数据分析平台。
值得一提的是在上述许多应用程序中数据科学家可能不会直接参与套接字的使用。他们通常使用库、框架和系统来抽象出套接字编程的所有低级细节。但是在后台所有这些解决方案都基于套接字通信并利用套接字编程。
套接字编程挑战和最佳实践
由于套接字是管理连接的低级概念因此使用套接字的开发人员必须实现所有必需的基础结构以创建健壮可靠的应用程序。这当然带来了很多挑战。但是可以遵循一些最佳实践和一般准则来克服这些问题。以下是套接字编程最常遇到的一些问题以及一些一般提示
连接管理
一次处理多个连接;管理多个客户端并确保有效处理并发请求肯定具有挑战性且并非易事。它需要仔细的资源管理和协调以避免瓶颈
最佳实践
使用列表或字典等数据结构跟踪活动连接。或者使用连接池等高级技术这也有助于提高可伸缩性。使用线程或异步编程技术同时处理多个客户端连接。正确关闭连接以释放资源并避免内存泄漏。
错误处理
处理连接失败、超时和数据传输问题等错误至关重要。处理这些错误并向客户端提供适当的反馈可能具有挑战性尤其是在进行低级套接字编程时。
最佳实践
使用 try-except-finally 块来捕获和处理特定类型的错误。提供信息丰富的错误消息并考虑使用日志记录来帮助进行故障排除。
可扩展性和性能
确保最佳性能和最小化延迟是处理大容量数据流或实时应用程序时的关键问题。
最佳实践
通过最大限度地减少不必要的数据处理和网络开销来优化代码以提高性能。实施缓冲技术以高效处理大型数据传输。考虑使用负载平衡技术在多个服务器实例之间分发客户端请求。
安全性和身份验证
保护基于套接字的通信并实施适当的身份验证机制可能很困难。确保数据隐私、防止未经授权的访问和防止恶意活动需要仔细考虑和实施安全协议。
最佳实践
利用 SSL/TLS 安全协议通过加密信息来确保数据传输的安全。通过实施安全的身份验证方法如基于令牌的身份验证、公钥加密或用户名/密码来确保客户端身份。确保机密数据如密码或 API 密钥得到保护和加密或者理想情况下根本不存储如果需要仅存储其哈希值。
网络可靠性和弹性
处理网络中断、带宽波动和不可靠的连接可能会带来挑战。保持稳定的连接、优雅地处理断开连接以及实施重新连接机制对于强大的网络应用程序至关重要。
最佳实践
使用保持活动状态消息检测非活动或断开的连接。实施超时以避免无限期阻塞并确保及时响应处理。实现指数退避重新连接逻辑以便在连接丢失时再次建立连接。
代码可维护性
最后但并非最不重要的一点是代码可维护性。由于套接字编程的低级性质开发人员发现自己编写了更多的代码。这可能会很快变成一个无法维护的意大利面条代码因此尽早组织和构建它并花费额外的精力来规划代码的体系结构至关重要。
最佳实践
将代码分解为类或函数理想情况下不应太长。通过模拟客户端和服务器实现来尽早编写单元测试请考虑使用更高级的库来处理连接除非绝对必须使用套接字编程。
总结Python 中的套接字编程
套接字是所有网络应用程序的组成部分。在本文中我们研究了 Python 中的套接字编程。以下是要记住的要点
套接字是抽象连接管理的接口。套接字支持不同进程通常是客户端和服务器之间的通信或者通过网络进行通信。在 Python 中使用套接字是通过库完成的该库为套接字对象提供了各种方法如、、、。socketrecvsendlistenclose套接字编程在数据科学中具有各种有用的应用包括数据收集、进程间通信和分布式计算。套接字编程面临的挑战包括连接管理、数据完整性、可伸缩性、错误处理、安全性和代码可维护性。
借助套接字编程技能开发人员可以创建高效、实时的网络应用程序。通过掌握概念和最佳实践他们可以充分利用套接字编程的潜力来开发可靠且可扩展的解决方案。
但是套接字编程是一种非常低级的技术很难使用因为应用程序工程师必须考虑应用程序通信的每一个小细节。
如今我们通常不需要直接使用套接字因为它们通常由更高级别的库和框架处理除非需要真正从应用程序中挤出性能或扩展它。
但是了解套接字并深入了解底层工作原理可以提高开发人员或数据科学家的整体意识并且始终是一个好主意。
原文链接Python 套接字编程完整指南 (mvrlink.com)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88793.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!