Python Penetration Testing 简明教程

The Socket and its Methods

套接字是双向通信信道的端点。它们可以在一个进程内、同一台计算机上的进程之间或不同计算机上的进程之间进行通信。类似地,网络套接字是两个通过因特网等计算机网络运行的程序之间通信流中的一个端点。它纯粹是一个虚拟的东西,不表示任何硬件。网络套接字可以通过 TCP、UDP 等许多不同的信道类型来实现。

网络编程中使用的与套接字相关的不同术语如下所述 -

Domain

域是指作为传输机制使用的协议族。这些值是常量,如 AF_INET、PF_INET、PF_UNIX、PF_X25 等。

Type

类型表示两个端点之间的通信类型,对于面向连接的协议通常为 SOCK_STREAM,对于无连接协议通常为 SOCK_DGRAM。

Protocol

这可用于识别域和类型内的协议变体。其默认值为 0。这通常会被省略。

Hostname

这可用作网络接口的标识符。主机名可以是字符串、点分四元组地址或冒号(也可能带有圆点)表示法的 IPV6 地址。

Port

每个服务器都会侦听调用一个或多个端口的客户端。端口可以是 Fixnum 端口号、包含端口号的字符串或服务的名称。

Python’s Socket Module for Socket Programming

要在 Python 中实现套接字编程,我们需要使用 Socket 模块。以下是创建一个 Socket 的简单语法 -

import socket
s = socket.socket (socket_family, socket_type, protocol = 0)

在此处,我们需要导入 socket 库,然后创建一个简单的 socket。以下是创建 socket 时使用的不同参数 -

  1. socket_family − 这是 AF_UNIX 或 AF_INET,如前文所述。

  2. socket_type − 这是 SOCK_STREAM 或 SOCK_DGRAM。

  3. protocol − 通常省略,默认为 0。

Socket Methods

在本节中,我们将学习不同的套接字方法。以下是三种不同的套接字方法集的说明 -

  1. Server Socket Methods

  2. Client Socket Methods

  3. General Socket Methods

Server Socket Methods

在客户端-服务器架构中,有一个提供服务的集中式服务器,并且许多客户端从该集中式服务器接收服务。客户端还会向服务器发送请求。以下是在此架构中的一些重要的服务器套接字方法 -

  1. socket.bind() - 此方法将地址(主机名、端口号)绑定到套接字。

  2. socket.listen() - 此方法基本上侦听对套接字进行的连接。它启动 TCP 侦听器。Backlog 是此方法的一个参数,它指定队列连接的最大数量。其最小值为 0,最大值为 5。

  3. socket.accept() - 这将接受 TCP 客户端连接。对(conn、address)是此方法的返回值对。此处,conn 是用于在连接上发送和接收数据的新的套接字对象,address 是绑定到套接字的地址。在使用此方法之前,必须使用 socket.bind() 和 socket.listen() 方法。

Client Socket Methods

客户端-服务器架构中的客户端请求服务器并从服务器接收服务。为此,仅有一个方法专门用于客户端 -

  1. socket.connect(address) − 此方法主动接受服务器连接,或者简单地说,此方法将客户端连接到服务器。参数地址代表服务器的地址。

General Socket Methods

除了客户端和服务器套接字方法之外,还有一些通用套接字方法,它们在套接字编程中非常有用。通用套接字方法如下所示 −

  1. socket.recv(bufsize) − 如名称所示,此方法从套接字接收 TCP 消息。参数 bufsize 代表缓冲区大小,并定义此方法在任何时候可以接收的最大数据量。

  2. socket.send(bytes) − 此方法用于将数据发送到已连接到远程计算机的套接字。参数 bytes 将给出发送到套接字的字节数。

  3. socket.recvfrom(data, address) − 此方法从套接字接收数据。此方法返回两个成对的(数据、地址)值。数据定义接收到的数据,而地址指定发送数据的套接字地址。

  4. socket.sendto(data, address) − 如名称所示,此方法用于从套接字发送数据。此方法返回两个成对的(数据、地址)值。数据定义发送的字节数,而地址指定远程计算机的地址。

  5. socket.close() − 此方法将关闭套接字。

  6. socket.gethostname() − 此方法将返回主机的名称。

  7. socket.sendall(data) − 此方法将所有数据发送到已连接到远程计算机的套接字。它会一直传输数据直到出错,如果发生这种情况,则它将使用 socket.close() 方法关闭套接字。

Program to establish a connection between server & client

若要建立服务器和客户端之间的连接,我们需要编写两个不同的 Python 程序,一个用于服务器,另一个用于客户端。

Server-side program

在此服务器端套接字程序中,我们将使用 socket.bind() 方法,该方法将其绑定到特定 IP 地址和端口,以便它可以侦听该 IP 和端口上的传入请求。然后,我们使用 socket.listen() 方法,该方法将服务器置于侦听模式。数字(例如 4)作为 socket.listen() 方法的参数表示,如果服务器正忙,则保持 4 个连接等待,如果第 5 个套接字尝试连接,则拒绝该连接。我们将使用 socket.send() 方法向客户端发送一条消息。最后,我们使用 socket.accept()socket.close() 方法分别启动和关闭连接。以下是一个服务器端程序 −

import socket
def Main():
   host = socket.gethostname()
   port = 12345
   serversocket = socket.socket()
   serversocket.bind((host,port))
   serversocket.listen(1)
   print('socket is listening')

   while True:
      conn,addr = serversocket.accept()
      print("Got connection from %s" % str(addr))
      msg = 'Connecting Established'+ "\r\n"
      conn.send(msg.encode('ascii'))
      conn.close()
if __name__ == '__main__':
   Main()

Client-side program

在客户端套接字程序中,我们需要创建一个套接字对象。然后,我们将连接到我们的服务器运行的端口——在我们的示例中是 12345。之后,我们将使用 socket.connect() 方法建立连接。然后,客户端将使用 socket.recv() 方法从服务器接收消息。最后, socket.close() 方法将关闭客户端。

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = socket.gethostname()
port = 12345

s.connect((host, port))
msg = s.recv(1024)

s.close()
print (msg.decode('ascii'))

现在,在运行服务器端程序之后,我们将获得终端上的以下输出 −

socket is listening
Got connection from ('192.168.43.75', 49904)

在运行客户端程序之后,我们将在另一个终端上获得以下输出 −

Connection Established

Handling network socket exceptions

tryexcept 这两个模块可以用来处理网络套接字异常。以下是一个用于处理异常的 Python 脚本 −

import socket
host = "192.168.43.75"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

try:
   s.bind((host,port))
   s.settimeout(3)
   data, addr = s.recvfrom(1024)
   print ("recevied from ",addr)
   print ("obtained ", data)
   s.close()
except socket.timeout :
   print ("No connection between client and server")
   s.close()

Output

上述程序生成以下输出 −

No connection between client and server

在上面的脚本中,我们首先创建了一个套接字对象。接下来,提供了我们的服务器正在运行的主机 IP 地址和端口号——在我们的示例中是 12345。然后,使用 try 块,并在其中使用 socket.bind() 方法,我们将尝试绑定 IP 地址和端口。我们使用 socket.settimeout() 方法来设置客户端的等待时间,在我们的示例中,我们设置了 3 秒。然后使用 except 块,如果服务器和客户端之间没有建立连接,它将打印一条消息。