socket库_Python实现TCP_IP客户和服务器通信

前言

套接字除了前文用于分析网络地址等功能之外,还可以配置一个服务器,监听到来的消息。

比如你在网络上跟网络机器人聊天,你发送数据到机器人(服务器),然后服务器反馈聊天数据信息给你。当然,机器人的回复还涉及机器学习,但简单的消息反馈涉及的就是套接字的知识。

而且,如果你直接将服务器配置为连接到其他应用的客户端,那么双向通信也可以实现。(比如聊天)

简单的搭建服务器与客户端

既然已经了解了套接字的应用。下面,我们来实现一个简单的单向通信TCP/IP服务器与客户端。

服务器

服务器的原理如下:

1.首先创建一个套接字,TCP是面向流的套接字。故需要使用SOCK_STREAM。

2.然后使用bind()函数将套接字与服务器地址关联(因为我们只是在本地测试,直接将地址设置为127.0.0.1或者localhost,端口号为10000),当然你身边如果有2台电脑设备,可以直接替换局域网的IP地址

3.调用listen()函数将套接字设置为服务器模式,然后无限循环等待,参数为最大排队数

4.在循环中,调用accept()等待客户端的消息连接(当然,这里可以设置最大连接数,超过直接拒绝连接)。如果有客户端进行连接,那么accept()函数会返回一个打开的连接与客户端地址

5.指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据

6.通过sendall()进行回传客户端数据。

7.传回数据后,与当前的客户端通信就算完成了。需要使用close()进行清理

示例代码如下:

import socket # 1.创建一个套接字, sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2.使用bind()函数将套接字与服务器地址关联 sock.bind((localhost, 10000)) # 3.调用listen()函数将套接字设置为服务器模式 sock.listen(1) while True: # 4.调用accept()等待客户端的消息连接 # 如果有客户端进行连接,那么accept()函数会返回一个打开的连接与客户端地址 connection, client_address = sock.accept() print("连接客户端地址:", client_address) try: # 5.指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据 data = connection.recv(1024) print(data) if data: # 6.通过sendall()进行回传客户端数据。 connection.sendall("已接受到数据".encode()) else: print("客户端没有发送数据,不需要传送数据") finally: #7.需要使用close()进行清理 connection.close()

客户端

实现客户端相对来说比服务器要简单的多,因为其不需要监听,只需要连接发送数据即可。客户端实现主要分为:

1.创建一个套接字

2.使用connect()函数连接到服务器

3.通过sendall()向服务器发送数据

4.通过recv()接受服务器传递回的数据

5.交互完成之后,使用close()清理

示例如下:

import socket # 1.创建一个套接字, sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2.使用bind()函数将套接字与服务器地址关联 sock.connect((localhost, 10000)) try: msg = b"Are you there?" # 3.通过sendall()向服务器发送数据 sock.sendall(msg) # 4.通过recv()接受服务器传递回的数据 data = sock.recv(1024) print(data.decode()) finally: # 5.交互完成之后,使用close()清理 sock.close()

运行之后,服务器与客户端交互效果如下:

create_connection(更简易的客户端)

连接服务器除了使用connect()函数之外,其实还有另一个函数create_connection()来连接服务器,它可以省略几个步骤。示例如下:

import socket # 获取匹配开头字符串的所有属性值 def getConstants(prefix): return { getattr(socket, n): n for n in dir(socket) if n.startswith(prefix) } ipproto_str = getConstants("IPPROTO_") family_str = getConstants("AF_") type_str = getConstants("SOCK_") sock = socket.create_connection((127.0.0.1, 10000)) print(ipproto_str[sock.proto]) print(family_str[sock.family]) print(type_str[sock.type]) try: msg = b"Are you there?" sock.sendall(msg) data = sock.recv(1024) print(data.decode()) finally: sock.close()

运行之后,效果如下:

create_connection()函数的原理是使用getaddrinfo()函数查找候选连接的参数,并返回一个打开的socket。getaddrinfo()函数的讲解在上一篇socket库。