套接字及其方法


套接字是双向通信通道的端点。它们可以在进程内、同一机器上的进程之间或不同机器上的进程之间进行通信。类似地,网络套接字是在计算机网络(例如 Internet)上运行的两个程序之间的通信流中的一个端点。它纯粹是一个虚拟的东西,不代表任何硬件。网络套接字可以通过 IP 地址和端口号的唯一组合来标识。网络套接字可以通过许多不同的通道类型(例如 TCP、UDP 等)来实现。

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

领域

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

类型

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

协议

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

主机名

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

港口

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

Python 的 Socket 模块用于套接字编程

要在python中实现socket编程,我们需要使用Socket模块。以下是创建 Socket 的简单语法 -

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

这里,我们需要导入socket库,然后制作一个简单的socket。以下是创建套接字时使用的不同参数 -

  • socket_family - 这是 AF_UNIX 或 AF_INET,如前所述。

  • socket_type - 这是 SOCK_STREAM 或 SOCK_DGRAM。

  • 协议- 这通常被忽略,默认为 0。

套接字方法

在本节中,我们将了解不同的套接字方法。下面描述了三组不同的套接字方法 -

  • 服务器套接字方法
  • 客户端套接字方法
  • 通用套接字方法

服务器套接字方法

在客户端-服务器架构中,有一台集中式服务器提供服务,许多客户端从该集中式服务器接收服务。客户端也向服务器发出请求。该架构中的一些重要的服务器套接字方法如下 -

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

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

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

客户端套接字方法

客户端-服务器架构中的客户端向服务器请求并接收来自服务器的服务。为此,只有一种专用于客户的方法 -

  • socket.connect(address) - 此方法主动建立服务器连接,或者简单地说,此方法将客户端连接到服务器。参数地址表示服务器的地址。

通用套接字方法

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

  • socket.recv(bufsize) - 顾名思义,此方法从套接字接收 TCP 消息。参数 bufsize 代表缓冲区大小,定义该方法在任一时间可以接收的最大数据。

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

  • socket.recvfrom(data, address) - 此方法从套接字接收数据。此方法返回两对(数据、地址)值。Data定义了接收到的数据,address指定了发送数据的socket地址。

  • socket.sendto(data, address) - 顾名思义,此方法用于从套接字发送数据。此方法返回两对(数据、地址)值。数据定义发送的字节数,地址指定远程机器的地址。

  • socket.close() - 此方法将关闭套接字。

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

  • socket.sendall(data) - 此方法将所有数据发送到连接到远程计算机的套接字。它会不小心地传输数据,直到发生错误,如果发生错误,它会使用 socket.close() 方法关闭套接字。

建立服务器和客户端之间的连接的程序

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

服务器端程序

在这个服务器端套接字程序中,我们将使用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()

客户端程序

在客户端socket程序中,我们需要制作一个socket对象。然后我们将连接到服务器运行的端口 - 在我们的示例中为 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

处理网络套接字异常

有两个块,即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()

输出

上述程序生成以下输出 -

No connection between client and server

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