前言
最近研究iOS设备与计算机通信时,涉及到了套接字,那到底什么是套接字?python中又如何实现套接字编程呢?带着疑问我们一起学习。
模块socket
网络编程中的一个基本组件是套接字(socket)。套接字基本上是一个信息通道,两端各有一个程序。这些程序可能位于(通过网络相连的)不同的计算机上,通过套接字向对方发送信息。其实说得通俗点,套接字就是一套用C语言写成的应用程序开发库,主要用于实现进程间通信和网络编程,在网络应用开发中被广泛使用。
套接字分为两类:服务器套接字和客户端套接字。创建服务器套接字后,让它等待连接请求的到来。这样,它将在某个网络地址(由IP地址和端口号组成)处监听,直到客户端套接字建立连接。随后,客户端和服务器就能通信了。
服务端套接字
我们先来看一段案例,实现一个提供时间日期的服务器:
python
from socket import socket, SOCK_STREAM, AF_INET
from datetime import datetime
def main():
# 1.创建套接字对象并指定使用哪种传输服务
# family=AF_INET - IPv4地址
# family=AF_INET6 - IPv6地址
# type=SOCK_STREAM - TCP套接字
# type=SOCK_DGRAM - UDP套接字
# type=SOCK_RAW - 原始套接字
server = socket(family=AF_INET, type=SOCK_STREAM)
# 2.绑定IP地址和端口(端口用于区分不同的服务)
# 同一时间在同一个端口上只能绑定一个服务否则报错
server.bind(('192.168.1.105', 6789))
# 3.开启监听 - 监听客户端连接到服务器
# 参数512可以理解为连接队列的大小
server.listen(512)
print('服务器启动开始监听...')
while True:
# 4.通过循环接收客户端的连接并作出相应的处理(提供服务)
# accept方法是一个阻塞方法如果没有客户端连接到服务器代码不会向下执行
# accept方法返回一个元组其中的第一个元素是客户端对象
# 第二个元素是连接到服务器的客户端的地址(由IP和端口两部分构成)
client, addr = server.accept()
print(str(addr) + '连接到了服务器.')
# 5.发送数据
client.send(str(datetime.now()).encode('utf-8'))
# 6.断开连接
client.close()
if __name__ == '__main__':
main()
可以看到这段代码是创建了一个TCP
套接字
运行服务器,测试一下:
MAC
yaml
nc 192.168.1.105 6666
顺利的话会输出当前时间。
windows
yaml
telnet 192.168.1.105 6666
客户端套接字
上面我们使用nc
命令来连接服务端,当然,我们也可以通过Python的程序来实现TCP客户端的功能,相较于实现服务器程序,实现客户端程序就简单多了。因为服务器必须准备随时处理客户端连接,还必须处理多个连接;而客户端只需连接,完成任务后再断开连接即可。
css
from socket import socket
def main():
# 1.创建套接字对象默认使用IPv4和TCP协议
client = socket()
# 2.连接到服务器(需要指定IP地址和端口)
client.connect(('192.168.1.105', 6666))
# 3.从服务器接收数据
print(client.recv(1024).decode('utf-8'))
client.close()
if __name__ == '__main__':
main()
总结
看了上面这个案例应该清晰很多了,服务器套接字先调用方法bind,再调用方法listen来监听特定的地址。然后,客户端套接字就可连接到服务器了,办法是调用方法connect并提供调用方法bind时指定的地址。这里的地址是一个格式为(host, port)的元组,其中host是主机名(如www.example.com),而port是端口号(一个整数)。方法listen接受一个参数------待办任务清单的长度(即最多可有多少个连接在队列中等待接纳,到达这个数量后将开始拒绝连接)。服务器套接字开始监听后,就可接受客户端连接了,这是使用方法accept来完成的。这个方法将阻断(等待)到客户端连接到来为止,然后返回一个格式为(client,address)的元组,其中client是一个客户端套接字,而address是前面解释过的地址。服务器能以其认为合适的方式处理客户端连接,然后再次调用accept以接着等待新连接到来。这通常是在一个无限循环中完成的。
传输数据,套接字提供了两个方法:send和recv(表示receive)。要发送数据,可调用方法send并提供一个字符串;要接收数据,可调用recv并指定最多接收多少个字节的数据。如果不确定该指定什么数字,1024是个不错的选择。
最后
我们上面讨论的服务器编程形式称为阻断(同步)网络编程。这也就意味着当服务器与一个客户端处于通信状态时,其他的客户端只能排队等待。很显然,这样的服务器并不能满足我们的需求,我们需要的服务器是能够同时接纳和处理多个用户请求的。之后我们在探索异步网络编程。