【理解】 Error 10053和 Error 10054

1. Error 10053 — Software caused connection abort

含义

  • 这个错误表示连接被本地软件(通常是你的程序或者操作系统)异常中止了。
  • 通常是应用层主动关闭连接,或者由于网络中断、超时等原因,导致本地网络栈中断了连接。

常见原因

  • 应用程序调用了 closesocket() 或者直接关闭了连接。
  • 应用程序超时未响应,操作系统为了释放资源主动关闭连接。
  • 防火墙或杀毒软件拦截了连接,强制关闭。
  • 网络不稳定,导致本地检测到错误并关闭连接。

典型场景

  • 客户端连接服务器时,中途客户端程序异常退出或者调用关闭。
  • 长时间无数据传输,某些设备或者操作系统超时关闭了连接。
  • 发送数据时本地网络栈检测到异常,终止连接。

2. Error 10054 — Connection reset by peer

含义

  • 连接被对端(远程主机)强制关闭,表现为“连接重置”。
  • 远程主机发送了 TCP RST(重置包),告诉本地主机连接异常被切断。

常见原因

  • 远程服务器程序崩溃、重启或异常退出。
  • 远程服务器主动调用关闭连接,且没有正常关闭流程。
  • 网络设备(防火墙、路由器)主动拒绝或重置连接。
  • 远程主机网络故障或重置连接。

典型场景

  • 客户端发送数据到服务器,服务器进程已关闭连接,返回 RST 包。
  • 远程主机超时未响应,主动断开连接。
  • 远程主机的防火墙策略拒绝当前连接。

3. 简单对比总结

错误码发生位置关闭主动方说明
10053本地本地主机本地软件主动中止连接
10054远端远程主机(对端)远程主机重置连接,强制关闭

4. 解决思路

  • 对于 10053
    • 检查本地应用程序是否合理关闭了套接字。
    • 排查防火墙、杀毒软件是否误拦截。
    • 增加超时和重连机制,避免长时间无响应被关闭。
  • 对于 10054
    • 检查服务器端程序是否异常退出或重启。
    • 查看服务器防火墙设置,是否主动拒绝连接。
    • 网络链路质量排查,避免中间设备断开。

好,给你准备了两个小工具示例,分别帮助你排查 Error 10053 和 Error 10054,以及示范如何在 Winsock 程序中捕获和处理这些错误。


1. 简单的网络状态检测脚本(Python)

这个脚本通过 TCP 连接目标服务器,检测连接是否正常,方便快速判断网络和服务器状态。

 

import socket

import sys

def test_connect(host, port):

try:

sock = socket.create_connection((host, port), timeout=5)

print(f"连接成功: {host}:{port}")

sock.close()

except socket.timeout:

print(f"连接超时: {host}:{port}")

except ConnectionResetError:

print(f"连接被远端重置 (Error 10054)")

except ConnectionAbortedError:

print(f"连接被本地中止 (Error 10053)")

except Exception as e:

print(f"连接失败: {e}")

if __name__ == "__main__":

if len(sys.argv) != 3:

print("用法: python test_connect.py <host> <port>")

sys.exit(1)

host = sys.argv[1]

port = int(sys.argv[2])

test_connect(host, port)

php

670 Bytes

© 菜鸟-创作你的创作

运行示例:

 

python test_connect.py 192.168.1.100 80

php

39 Bytes

© 菜鸟-创作你的创作


2. Winsock 错误捕获示例(C++)

演示如何在 Winsock TCP 客户端程序中捕获 10053 和 10054 错误,并做相应处理。

 

#include <winsock2.h>

#include <ws2tcpip.h>

#include <iostream>

#pragma comment(lib, "ws2_32.lib")

int main() {

WSADATA wsaData;

SOCKET sock = INVALID_SOCKET;

sockaddr_in serverAddr;

WSAStartup(MAKEWORD(2, 2), &wsaData);

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sock == INVALID_SOCKET) {

std::cerr << "socket error: " << WSAGetLastError() << std::endl;

WSACleanup();

return 1;

}

serverAddr.sin_family = AF_INET;

serverAddr.sin_port = htons(80);

inet_pton(AF_INET, "192.168.1.100", &serverAddr.sin_addr);

int ret = connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr));

if (ret == SOCKET_ERROR) {

int err = WSAGetLastError();

if (err == 10053) {

std::cerr << "Error 10053: Connection aborted locally." << std::endl;

// 处理本地中止逻辑

} else if (err == 10054) {

std::cerr << "Error 10054: Connection reset by peer." << std::endl;

// 处理远程重置逻辑

} else {

std::cerr << "连接失败,错误码: " << err << std::endl;

}

closesocket(sock);

WSACleanup();

return 1;

}

// 连接成功,发送/接收代码

closesocket(sock);

WSACleanup();

return 0;

}

php

1.21 KB

© 菜鸟-创作你的创作


3. 处理建议

  • 捕获到 10053 错误时,建议检查是否应用层逻辑关闭了套接字,或者添加重连逻辑。
  • 捕获到 10054 错误时,建议排查服务器端是否异常关闭连接,同时做好断线重连处理。

好,我给你写一个带自动重连机制的 WinSock TCP 客户端示例,示范如何捕获错误 10053、10054 并尝试重连。

 

#include <winsock2.h>

#include <ws2tcpip.h>

#include <iostream>

#include <thread>

#include <chrono>

#pragma comment(lib, "ws2_32.lib")

bool connect_to_server(SOCKET& sock, const sockaddr_in& serverAddr) {

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sock == INVALID_SOCKET) {

std::cerr << "Socket 创建失败,错误码:" << WSAGetLastError() << std::endl;

return false;

}

if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {

int err = WSAGetLastError();

std::cerr << "连接失败,错误码:" << err << std::endl;

closesocket(sock);

sock = INVALID_SOCKET;

return false;

}

std::cout << "连接服务器成功!" << std::endl;

return true;

}

void run_client(const char* ip, unsigned short port) {

WSADATA wsaData;

if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {

std::cerr << "WSAStartup失败" << std::endl;

return;

}

sockaddr_in serverAddr{};

serverAddr.sin_family = AF_INET;

serverAddr.sin_port = htons(port);

inet_pton(AF_INET, ip, &serverAddr.sin_addr);

SOCKET sock = INVALID_SOCKET;

const int max_retries = 5;

int retry_count = 0;

while (true) {

if (sock == INVALID_SOCKET) {

if (!connect_to_server(sock, serverAddr)) {

retry_count++;

if (retry_count > max_retries) {

std::cerr << "重连超过最大次数,退出程序" << std::endl;

break;

}

std::cout << "等待3秒后重连..." << std::endl;

std::this_thread::sleep_for(std::chrono::seconds(3));

continue;

}

retry_count = 0; // 成功连接,重置计数

}

// 发送数据示例

const char* msg = "Hello server";

int ret = send(sock, msg, (int)strlen(msg), 0);

if (ret == SOCKET_ERROR) {

int err = WSAGetLastError();

std::cerr << "发送数据失败,错误码:" << err << std::endl;

if (err == 10053) {

std::cerr << "本地中止连接(10053),尝试重连" << std::endl;

} else if (err == 10054) {

std::cerr << "远程重置连接(10054),尝试重连" << std::endl;

} else {

std::cerr << "其他错误,退出" << std::endl;

break;

}

closesocket(sock);

sock = INVALID_SOCKET;

continue;

}

// 接收数据示例(简化)

char buf[512];

ret = recv(sock, buf, sizeof(buf) - 1, 0);

if (ret == 0) {

std::cerr << "连接关闭,尝试重连" << std::endl;

closesocket(sock);

sock = INVALID_SOCKET;

continue;

} else if (ret == SOCKET_ERROR) {

int err = WSAGetLastError();

std::cerr << "接收数据失败,错误码:" << err << std::endl;

if (err == 10053 || err == 10054) {

std::cerr << "连接异常断开,尝试重连" << std::endl;

closesocket(sock);

sock = INVALID_SOCKET;

continue;

} else {

std::cerr << "其他错误,退出" << std::endl;

break;

}

} else {

buf[ret] = '\0';

std::cout << "收到数据: " << buf << std::endl;

}

std::this_thread::sleep_for(std::chrono::seconds(5)); // 模拟间隔

}

if (sock != INVALID_SOCKET) {

closesocket(sock);

}

WSACleanup();

}

int main() {

const char* server_ip = "192.168.1.100";

unsigned short server_port = 80;

run_client(server_ip, server_port);

return 0;

}

php

3.42 KB

© 菜鸟-创作你的创作


说明:

  • 失败时针对错误 10053/10054 关闭 socket 并重连,最多重连 5 次。
  • 每次重连间隔 3 秒。
  • 简单模拟发送“Hello server”,接收数据。
  • 其他错误会退出程序。

明白!我帮你写一个基于之前代码的多线程版 Winsock TCP 客户端,包含:

  • 独立线程做连接和自动重连
  • 主线程处理数据收发
  • 线程安全退出机制
  • 错误日志写文件

 

#include <winsock2.h>

#include <ws2tcpip.h>

#include <iostream>

#include <thread>

#include <atomic>

#include <chrono>

#include <fstream>

#include <mutex>

#pragma comment(lib, "ws2_32.lib")

std::atomic<bool> running{ true };

std::mutex log_mutex;

void log_error(const std::string& msg) {

std::lock_guard<std::mutex> lock(log_mutex);

std::ofstream log("client_error.log", std::ios::app);

log << msg << std::endl;

std::cerr << msg << std::endl;

}

bool connect_to_server(SOCKET& sock, const sockaddr_in& serverAddr) {

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sock == INVALID_SOCKET) {

log_error("Socket 创建失败,错误码:" + std::to_string(WSAGetLastError()));

return false;

}

if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {

int err = WSAGetLastError();

log_error("连接失败,错误码:" + std::to_string(err));

closesocket(sock);

sock = INVALID_SOCKET;

return false;

}

std::cout << "连接服务器成功!" << std::endl;

return true;

}

void connection_manager(SOCKET& sock, const sockaddr_in& serverAddr) {

const int max_retries = 5;

int retry_count = 0;

while (running) {

if (sock == INVALID_SOCKET) {

if (!connect_to_server(sock, serverAddr)) {

retry_count++;

if (retry_count > max_retries) {

log_error("重连超过最大次数,停止连接管理线程");

running = false;

break;

}

log_error("等待3秒后重连...");

std::this_thread::sleep_for(std::chrono::seconds(3));

continue;

}

retry_count = 0;

}

std::this_thread::sleep_for(std::chrono::seconds(1));

}

}

void data_handler(SOCKET& sock) {

while (running) {

if (sock == INVALID_SOCKET) {

std::this_thread::sleep_for(std::chrono::milliseconds(200));

continue;

}

// 发送示例

const char* msg = "Hello server";

int ret = send(sock, msg, (int)strlen(msg), 0);

if (ret == SOCKET_ERROR) {

int err = WSAGetLastError();

log_error("发送失败,错误码:" + std::to_string(err));

if (err == 10053 || err == 10054) {

log_error("连接异常断开,准备重连");

closesocket(sock);

sock = INVALID_SOCKET;

continue;

} else {

log_error("未知错误,停止程序");

running = false;

break;

}

}

// 接收示例

char buf[512];

ret = recv(sock, buf, sizeof(buf) - 1, 0);

if (ret == 0) {

log_error("服务器关闭连接,准备重连");

closesocket(sock);

sock = INVALID_SOCKET;

continue;

}

else if (ret == SOCKET_ERROR) {

int err = WSAGetLastError();

log_error("接收失败,错误码:" + std::to_string(err));

if (err == 10053 || err == 10054) {

log_error("连接异常断开,准备重连");

closesocket(sock);

sock = INVALID_SOCKET;

continue;

} else {

log_error("未知错误,停止程序");

running = false;

break;

}

}

else {

buf[ret] = '\0';

std::cout << "收到数据: " << buf << std::endl;

}

std::this_thread::sleep_for(std::chrono::seconds(5));

}

}

int main() {

WSADATA wsaData;

if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {

log_error("WSAStartup失败");

return 1;

}

sockaddr_in serverAddr{};

serverAddr.sin_family = AF_INET;

serverAddr.sin_port = htons(80);

inet_pton(AF_INET, "192.168.1.100", &serverAddr.sin_addr);

SOCKET sock = INVALID_SOCKET;

std::thread conn_thread(connection_manager, std::ref(sock), std::ref(serverAddr));

std::thread data_thread(data_handler, std::ref(sock));

std::cout << "按回车退出程序..." << std::endl;

std::cin.get();

running = false;

conn_thread.join();

data_thread.join();

if (sock != INVALID_SOCKET) {

closesocket(sock);

}

WSACleanup();

return 0;

}

php

4.09 KB

© 菜鸟-创作你的创作


说明:

  • connection_manager 线程负责连接和重连,最多尝试 5 次失败后停止程序。
  • data_handler 线程负责数据收发,检测错误 10053 和 10054 后关闭连接,等待重连。
  • 采用 std::atomic<bool> 控制线程退出。
  • 所有错误日志写入 client_error.log,同时输出到控制台。
  • 主线程等待用户回车后,安全退出所有线程和清理资源。

好,这里帮你写一个简单的 CMakeLists.txt,用于编译上面那个多线程 Winsock TCP 客户端示例。这个配置适合 Windows 平台,使用 Visual Studio 或者命令行编译。


CMakeLists.txt

 

cmake_minimum_required(VERSION 3.10)

project(WinSockClientMultiThread LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(WinSockClientMultiThread main.cpp)

# 链接 Winsock 库

target_link_libraries(WinSockClientMultiThread PRIVATE ws2_32)

php

279 Bytes

© 菜鸟-创作你的创作


使用步骤

  1. 把你写好的 C++ 代码保存为 main.cpp(与 CMakeLists.txt 同目录)。
  2. 打开命令行(PowerShell 或 cmd),进入项目目录。
  3. 生成 Visual Studio 解决方案(假设你安装了 Visual Studio 和 CMake):
 

mkdir build

cd build

cmake .. -G "Visual Studio 17 2022" # 或根据你的 VS 版本替换生成器

php

77 Bytes

© 菜鸟-创作你的创作

  1. 编译:
  • 在 Visual Studio 里打开生成的解决方案,编译运行。
  • 或者直接用命令行编译:
 

cmake --build . --config Release

php

32 Bytes

© 菜鸟-创作你的创作

  1. 编译成功后,在 build/Release 目录下会生成 WinSockClientMultiThread.exe,直接运行。

【理解】 Error 10053和 Error 10054 - 菜鸟-创作你的创作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值