对于这个错误码的解释网上有很多,就是链接被远程主机重置,说实话这句话说了和没说一样,根本不知道啥意思,于是就各种查
对于10054可能的出现原因,一个大佬总结的很好,我这里直接搬运过来
对端关闭了socket(可能是异常也可能是超时),然而本端还没有感知到,依旧写入数据(对端接收缓冲区有数据),对端发现有未处理的数据直接回复RST重置连接标记,表明对端已经关闭了socket
检测出这个错误码一般是对端发送了RST包给本端,本端接收这个包, 表示对端出现了异常: 四种情况发送RST码:
1. 本端连接对端未打开的端口, 对端发送RST包
2. 请求超时
3. 已关闭连接上收到数据:
主要出现在连接的关闭过程,当请求关闭连接的一方在两个MSL后,仍然收到服务机发送来的最后一个FIN,说明其最后发送出的ACK丢包, 服务机又重发了FIN包,而此时客户机已经不处于TIME_OUT状态,连接已经彻底不存在,再收到服务机发送来的FIN,就会直接回复一个RST包,让服务机直接关闭连接,抛弃 缓冲区的所有数据。
举一个其他例子: 主动端关闭socket,发送了fin给被动端,此时主动端无法接受和发送数据了,此时如果被动端调用read会收到fin(读取0),如果被动端write给主动端,主动端会发送rst,但rst不会立即通知到被动段,只有被动端在第二次write时,数据不会发送给主动端而是发出一个SIGPIPE信号而终止被动端(可捕获忽略该信号)
4. close连接时, 接收缓冲区还有数据
如果close连接时,接收缓冲区还有对端发过来的数据,则回一个RST,直接丢弃接收缓冲区的内容
5. 设置了so_linger选项但是 l_onoff 不为0,l_linger为0, 此时close系统调用立即结束,TCP模块将丢弃被关闭的socket对应的TCP发送缓冲区中残留的数据,同时回给对方一个RST
上面提到的主动端是指客户端,被动端指服务端
下面贴出可以浮现的代码
首先是客户端
/* * @Author: windofbarcelona * @Date: * @LastEditTime: * @LastEditors: Please set LastEditors * @Description: In User Settings Edit */
#include<iostream>
#include<WinSock2.h>
#include<string>
#include<vector>
#include<fstream>
#include<io.h>
#include<algorithm>
#pragma comment(lib, "Ws2_32.lib")
#pragma warning(disable : 4996)
using namespace std;
int main() {
WORD VersionRequested;
WSADATA WsaData;
VersionRequested = MAKEWORD(2, 2);
if (WSAStartup(VersionRequested, &WsaData))
return -1;
SOCKET SocketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN AddrServer;
AddrServer.sin_addr.S_un.S_addr = inet_addr("192.168.1.100");
AddrServer.sin_port = htons(9999);
AddrServer.sin_family = AF_INET;
if (0 != connect(SocketServer, (SOCKADDR*)&AddrServer, sizeof(SOCKADDR)))
{
closesocket(SocketServer);
cout << "connect error:" << WSAGetLastError() << endl;
return false;
}
int err = 0;
char temp[] = "hello, server";
int rs = send(SocketServer, temp, sizeof(temp) + 1, 0);
cout << "first send:" << rs << endl;
char buff[1024] = {
0 };
rs = recv(SocketServer, buff, sizeof(buff), 0);
cout << "first recv:" << rs << endl;
rs = send(SocketServer, temp, sizeof(temp) + 1, 0);
err = WSAGetLastError();
cout << "second send:" << rs << ",error:" << err << endl;
rs = recv(SocketServer, buff, sizeof(buff), 0);
err = WSAGetLastError();
cout << "second recv:" << rs << ",error:" << err << endl;
closesocket(SocketServer);
WSACleanup();
system("pause");
return 0;
}
然后是服务端的代码
/* * @Author: windofbarcelona * @Date: * @LastEditTime: * @LastEditors: Please set LastEditors * @Description: In User Settings Edit */
#include<iostream>
#include<WinSock2.h>
#include<string>
#include<vector>
#include<fstream>
#include<io.h>
#include<algorithm>
#pragma comment(lib, "Ws2_32.lib")
#pragma warning(disable : 4996)
using namespace std;
int main() {
WORD VersionRequested;
WSADATA WsaData;
VersionRequested = MAKEWORD(2, 2);
if (WSAStartup(VersionRequested, &WsaData))
{
printf("加载socket库失败!\n");
return -1;
}
// 监听来自浏览器的请求
SOCKET SockServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN AddrClient;
AddrClient.sin_family = AF_INET;
AddrClient.sin_addr.s_addr = INADDR_ANY;
AddrClient.sin_port = htons(9999);
if (SockServer == INVALID_SOCKET)
{
printf("socket初始化失败!\n");
closesocket(SockServer);
WSACleanup();
return -1;
}
if (bind(SockServer, (sockaddr*)&AddrClient, sizeof(AddrClient)) != 0)
{
printf("socket绑定失败!\n");
closesocket(SockServer);
WSACleanup();
return -1;
}
if (listen(SockServer, 10) != 0)
{
printf("socket监听失败!\n");
closesocket(SockServer);
WSACleanup();
return -1;
}
while (1)
{
SOCKET NewSocket = accept(SockServer, NULL, NULL);
if (INVALID_SOCKET == NewSocket)
{
closesocket(NewSocket);
continue;
}
else
{
//plan A
struct linger so_linger;
so_linger.l_onoff = 10;
so_linger.l_linger = 0;
setsockopt(NewSocket, SOL_SOCKET, SO_LINGER, (const char*)&so_linger, sizeof(so_linger));
}
char buff[1024];
int rs = recv(NewSocket, buff, sizeof(buff), 0);
cout << "recv:" << rs << endl;
char temp[] = "hello, client";
rs = send(NewSocket, temp, sizeof(temp) + 1, 0);
cout << "send:" << rs << endl;
//Sleep(3000); plan B
closesocket(NewSocket);
}
return 0;
}
说明,服务端的代码提供了plan A和plan B两种方式,都可以出现10054的错误
对于plan A就是上面原因5说明的
对于plan B就是上面的原因4,close的时候接收缓冲区中还有未处理的数据,于是放弃数据 直接回RST,我在服务端设置延时是为了,在关闭的时候,客户端的数据一定发过来了
上面的代码可以同时用wireshark进行抓包观察
代码运行环境说明,用了两台 win10系统的电脑进行测试,在服务端的主机上用wireshark进行抓包观察
解决方案我觉得就是得分析协议的实现是否出现了问题,导致了10054的发生
参考链接:
https://www.cnblogs.com/pengyusong/p/6433516.html
http://www.blogjava.net/pandawang/archive/2013/11/28/406922.html
今天的文章ms08067复现_code500错误原因解决方法[通俗易懂]分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/77462.html