343-TCP服务器程序入口与端口复用
端口复用:
在上一次关闭服务器后,端口不会立即释放,需要设置端口复用,才能继续使用此端口
import socket
class WebServer:
# 3、定义一个__init__方法,初始化套接字对象
def __init__(self):
self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用(在上一次关闭服务器后,端口不会立即释放,需要设置端口复用)
self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 参数2:SOL_SOCKET表示当前套接字对象,参数3:SO_REUSEADDR表示复用的地址,参数4:True表示开启端口复用(默认是false,要等待很长时间端口才会自动释放)
self.tcp_server_socket.bind(("127.0.0.1", 8000)) # 如果是本机,可以不写ip地址
self.tcp_server_socket.listen(128) # 128表示最大连接数
# 4、定义一个start方法,启动服务器,接收客户端连接
def start(self):
while True:
# 等待接受客户端的连接请求
new_socket, ip_port = self.tcp_server_socket.accept()
# 调用自身的handle_request()方法,用于接收和发送消息(封装性)
self.handle_request(new_socket, ip_port)
# 5、定义一个handle_request方法,用于接收和发送消息
def handle_request(self, new_socket, ip_port):
# 接收某个客户端发送过来的消息
recv_data = new_socket.recv(1024).decode("utf-8") # 实际工作中一条数据大小在1~1.5k之间
print(f"接收到的数据为:{recv_data}")
# 发送消息给客户端
new_socket.send("信息已收到".encode("utf-8"))
# 关闭套接字
new_socket.close()
# 定义一个程序的执行入口
if __name__ == "__main__":
# 1、实例化服务器对象
server = WebServer()
# 2、启动服务器
server.start()
开发注意事项
1.当TCP客户端程序想要和TCP服务端程序进行通信的时候必须要先建立连接
2.TCP客户端程序一般不需要绑定端口号,因为客户端是主动发起建立连接的。
3.TCP服务端程序必须绑定端口号,否则客户端找不到这个TCP服务端程序。
4.listen后的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息。
5.当TCP客户端程序和TCP服务端程序连接成功后,TCP服务器端程序会产生一个新的套接字,收发客户端消息使用该套接字。
6.关闭accept返回的套接字意味着和这个客户端已经通信完毕。
7.当客户端的套接字调用close后,服务器端的recv会解阻塞,返回的数据长度为O,服务端可以通过返回数据的长度来判断客户端是否
已经下线,反之服务端关闭套接字,客户端的recv也会解阻塞,返回的数据长度也为0。
UDP客户端
# 导入socket模块
import socket
# 创建UDP套接字对象
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 连接服务器,发送数据
udp_socket.sendto("消息".encode("utf-8"), ("127.0.0.1", 8000))
# 关闭套接字
udp_socket.close()