套接字及其方法
套接字是双向通信通道的端点。它们可以在一个进程内、同一台机器上的进程之间或不同机器上的进程之间进行通信。类似地,网络套接字是在计算机网络(例如互联网)上运行的两个程序之间通信流中的一个端点。它纯粹是一个虚拟事物,并不代表任何硬件。网络套接字可以通过IP地址和端口号的唯一组合来标识。网络套接字可以基于多种不同的通道类型实现,例如TCP、UDP等等。
网络编程中使用的与套接字相关的不同术语如下:
域
域是指用作传输机制的协议族。这些值是常量,例如AF_INET、PF_INET、PF_UNIX、PF_X25等等。
类型
类型表示两个端点之间的通信类型,通常对于面向连接的协议为SOCK_STREAM,对于无连接的协议为SOCK_DGRAM。
协议
这可以用来标识域和类型内协议的变体。其默认值为0。这通常被忽略。
主机名
这作为网络接口的标识符。主机名可以是字符串、点分四元组地址或冒号(可能还有点)表示法的IPV6地址。
端口
每个服务器监听一个或多个端口上的客户端调用。端口可以是Fixnum端口号、包含端口号的字符串或服务的名称。
Python的Socket模块用于套接字编程
要在Python中实现套接字编程,我们需要使用Socket模块。以下是创建套接字的简单语法:
import socket s = socket.socket (socket_family, socket_type, protocol = 0)
在这里,我们需要导入socket库,然后创建一个简单的套接字。以下是创建套接字时使用的不同参数:
**socket_family** - 如前所述,这是AF_UNIX或AF_INET。
**socket_type** - 这是SOCK_STREAM或SOCK_DGRAM。
**protocol** - 这通常被忽略,默认为0。
套接字方法
在本节中,我们将学习不同的套接字方法。下面描述了三组不同的套接字方法:
- 服务器套接字方法
- 客户端套接字方法
- 通用套接字方法
服务器套接字方法
在客户端-服务器架构中,有一个集中的服务器提供服务,许多客户端从该集中式服务器接收服务。客户端也向服务器发出请求。此架构中一些重要的服务器套接字方法如下:
**socket.bind()** - 此方法将地址(主机名、端口号)绑定到套接字。
**socket.listen()** - 此方法基本上监听与套接字建立的连接。它启动TCP监听器。Backlog是此方法的参数,它指定排队连接的最大数量。其最小值为0,最大值为5。
**socket.accept()** - 这将接受TCP客户端连接。对(conn, address)是此方法的返回值对。这里,conn是一个新的套接字对象,用于在连接上发送和接收数据,而address是绑定到套接字的地址。在使用此方法之前,必须使用socket.bind()和socket.listen()方法。
客户端套接字方法
在客户端-服务器架构中,客户端请求服务器并从服务器接收服务。为此,只有一个专用于客户端的方法:
**socket.connect(address)** - 此方法主动启动服务器连接,或者简单地说,此方法将客户端连接到服务器。参数address表示服务器的地址。
通用套接字方法
除了客户端和服务器套接字方法之外,还有一些通用套接字方法在套接字编程中非常有用。通用套接字方法如下:
**socket.recv(bufsize)** - 顾名思义,此方法从套接字接收TCP消息。参数bufsize代表缓冲区大小,定义此方法在任何时候可以接收的最大数据量。
**socket.send(bytes)** - 此方法用于向连接到远程机器的套接字发送数据。参数bytes将给出发送到套接字的字节数。
**socket.recvfrom(data, address)** - 此方法从套接字接收数据。此方法返回两对(data, address)值。Data定义接收到的数据,address指定发送数据的套接字的地址。
**socket.sendto(data, address)** - 顾名思义,此方法用于从套接字发送数据。此方法返回两对(data, address)值。Data定义发送的字节数,address指定远程机器的地址。
**socket.close()** - 此方法将关闭套接字。
**socket.gethostname()** - 此方法将返回主机的名称。
**socket.sendall(data)** - 此方法将所有数据发送到连接到远程机器的套接字。它将不间断地传输数据,直到发生错误,如果发生错误,则它使用socket.close()方法关闭套接字。
建立服务器和客户端之间连接的程序
要建立服务器和客户端之间的连接,我们需要编写两个不同的Python程序,一个用于服务器,另一个用于客户端。
服务器端程序
在这个服务器端套接字程序中,我们将使用**socket.bind()**方法将其绑定到特定的IP地址和端口,以便它可以监听该IP和端口上的传入请求。稍后,我们将使用**socket.listen()**方法将服务器置于监听模式。例如,作为**socket.listen()**方法参数的数字4意味着如果服务器繁忙,则最多保持4个连接等待,如果第五个套接字尝试连接,则连接将被拒绝。我们将使用**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()
客户端程序
在客户端套接字程序中,我们需要创建一个套接字对象。然后,我们将连接到服务器正在运行的端口——在我们的示例中为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
处理网络套接字异常
可以使用**try**和**except**两个块来处理网络套接字异常。以下是用于处理异常的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块用于在服务器和客户端之间未建立连接时打印消息。