Python Socket服务器触发WinError 10038,无法持续监听新连接求助
问题:Socket服务器处理单次请求后触发WinError 10038错误
我开发了一个基于Python Socket的服务器,集成SQLite数据库、人脸识别功能,实现用户登录与注册服务。目前服务器可处理单次客户端请求,但处理完成后会触发[WinError 10038]错误,无法继续等待新用户连接。
服务器代码
import sqlite3 import socket import re import face_recognition import os, sys import cv2 import numpy as np import math from recognition import FaceRecognizer from SalaryDemo import Salary from Camera import SignUpCamera def main(): # Connect to the SQLite database conn = sqlite3.connect('users.db') cursor = conn.cursor() cursor.execute("PRAGMA table_info('users')") result = cursor.fetchone() if not result: # If the 'users' table does not exist, create it cursor.execute('''CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT)''') cursor.execute("ALTER TABLE users ADD COLUMN user_data TEXT") # Set up the server server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('localhost', 8080)) server.listen() open = True # Wait for incoming connections client, addr = server.accept() print(f'Connected by {addr}') while True: # Receive login/sign-up data from the client data = client.recv(1024) action, username, password = data.decode().split(':') if action == 'login': recognizer = FaceRecognizer() recognizer.load_faces("faces") if recognizer.recognize_face(username): cursor.execute('SELECT * FROM users WHERE username = ? AND password = ?', (username, password)) result = cursor.fetchone() else: print(f"{username} not matched!") result = None if result: # If the login is successful, send the user's data back to the client user_data = f'{result[0]}:{result[1]}:{result[2]}' msg_to_client = "welcome " + username client.send(msg_to_client.encode()) sl = Salary() sl.getSallary(username) else: # If the login is unsuccessful, send an error message back to the client client.send('Invalid login'.encode()) elif action == 'signup': cm = SignUpCamera() # Check if the password is strong enough if not re.search(r'[A-Z]', password) or not re.search(r'[a-z]', password) or not re.search(r'[0-9]', password): client.send('Password is not strong enough'.encode()) else: # Check if the username is already in use cursor.execute('SELECT * FROM users WHERE username = ?', (username,)) result = cursor.fetchone() if result: # If the username is already in use, send an error message back to the client client.send('Username already in use'.encode()) else: # If the username is available, insert a new row into the 'users' table cursor.execute("INSERT INTO users (username, password, user_data) VALUES (?, ?, ? || '.jpg')", (username, password, username.lower())) conn.commit() cm.main(username) client.send('Sign-up successful'.encode()) client.close() if __name__ == "__main__": main()
报错信息
Message=[WinError 10038] An operation was attempted on something that is not a socket Source=C:\Users\Bar12\source\repos\final-project-afek-and-liam-authentication_client_server\ServerSideProject\ServerSideProject\ServerSideProject.py StackTrace: File "C:\Users\Bar12\source\repos\final-project-afek-and-liam-authentication_client_server\ServerSideProject\ServerSideProject\ServerSideProject.py", line 89, in <module> main()
问题分析与修复方案
问题根源
- 客户端Socket提前关闭:
client.close()被放在了while True循环内部,处理完一次请求就关闭了客户端连接,但循环还会继续执行client.recv(),此时client已经不是有效的Socket对象,触发WinError 10038。 - 仅接受一次客户端连接:
server.accept()只被调用了一次,服务器只能处理第一个客户端的请求,无法接收后续新的客户端连接。
修改后的代码
import sqlite3 import socket import re import face_recognition import os, sys import cv2 import numpy as np import math from recognition import FaceRecognizer from SalaryDemo import Salary from Camera import SignUpCamera def main(): # Connect to the SQLite database conn = sqlite3.connect('users.db') cursor = conn.cursor() cursor.execute("PRAGMA table_info('users')") result = cursor.fetchone() if not result: # If the 'users' table does not exist, create it cursor.execute('''CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT)''') cursor.execute("ALTER TABLE users ADD COLUMN user_data TEXT") # Set up the server server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('localhost', 8080)) server.listen() print("Server started, waiting for connections...") # 外层循环:持续接受新的客户端连接 while True: client, addr = server.accept() print(f'Connected by {addr}') try: # 内层循环:处理当前客户端的请求(支持单客户端多次请求) while True: # Receive login/sign-up data from the client data = client.recv(1024) if not data: # 客户端断开连接时,recv返回空 break action, username, password = data.decode().split(':') if action == 'login': recognizer = FaceRecognizer() recognizer.load_faces("faces") if recognizer.recognize_face(username): cursor.execute('SELECT * FROM users WHERE username = ? AND password = ?', (username, password)) result = cursor.fetchone() else: print(f"{username} not matched!") result = None if result: msg_to_client = "welcome " + username client.send(msg_to_client.encode()) sl = Salary() sl.getSallary(username) else: client.send('Invalid login'.encode()) elif action == 'signup': cm = SignUpCamera() # Check if the password is strong enough if not re.search(r'[A-Z]', password) or not re.search(r'[a-z]', password) or not re.search(r'[0-9]', password): client.send('Password is not strong enough'.encode()) else: # Check if the username is already in use cursor.execute('SELECT * FROM users WHERE username = ?', (username,)) result = cursor.fetchone() if result: client.send('Username already in use'.encode()) else: cursor.execute("INSERT INTO users (username, password, user_data) VALUES (?, ?, ? || '.jpg')", (username, password, username.lower())) conn.commit() cm.main(username) client.send('Sign-up successful'.encode()) except Exception as e: print(f"Error handling client {addr}: {e}") finally: # 处理完当前客户端请求后关闭连接 client.close() print(f"Disconnected from {addr}") if __name__ == "__main__": main()
修改说明
- 将
server.accept()放入外层while True循环,确保服务器能持续接受新的客户端连接。 - 把
client.close()移到finally块中,确保无论是否发生异常,客户端连接都会被正确关闭。 - 添加了
if not data:判断,当客户端主动断开连接时,内层循环退出,避免无效的recv调用。 - 增加异常捕获,方便排查客户端处理过程中的错误。
内容的提问来源于stack exchange,提问作者Afek Barda
相关产品推荐
相关产品推荐

