网络编程(socket).WinSocket_recvfrom出错,GetLastError()为10054
1、在写 我的Qt598(vs2017)x64版本的 shadowsocks程序时遇到的。
具体问题情况 大概是这样:QUdpSocket(假设是sktA) connect接收函数,sktA侦听 端口9999,然后 sktA向本机端口9989发数据,然后现象是 接收函数中 QUdpSocket::hasPendingDatagrams()返回true,QUdpSocket::pendingDatagramSize()有反应,但是返回的数值是0,此时 sktA再向本机9989发送数据,接收函数 接收函数 再也没有反映了...
ZC:我之前的 猜测:sktA侦听,但是 它侦听到了 不该它侦听的端口的信息,导致了错误,然后我就朝着这个方向 查了好多资料... ∵ 确实是 接收函数 有反映了... 然后我查到了 有人说他只能接收一次数据 后面的数据接收不到的情况,他的原因是 之前的 数据没有处理,导致数据堵在那里了。 我觉得和我的现象很像,sktA接收到了 不该它接收的端口的信息,于是 就堵了 接收函数再也没反映了...(现在想想 还一种情况:向 9989 发送数据 没反应之后,再向 9999发数据的话 接收函数 还会有反应吗?? 测试了一下,没反应了,就像是 接收函数 挂掉了,或者说 QUdpSocket挂掉了?)
ZC:后来 没辙了,就尝试 VC(vs2017+Win10x64) 会不会也有此种情况,发现 确实 recvfrom会报错 GetLastError()返回 10054,从这里 找到了 真正的原因:由于 9989端口的数据 不可达,于是返回了 不可达的ICMP数据,然后 QUdpSocket错误的以为是 接收到了数据??(为啥此种情况 QUdpSocket connect的异常输出函数没反应??)然后 接收函数 就不工作了???
2、
3、在 Qt中设置之后,上面的现象 也没有了
3.1、Qt中 这样设置:
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12)
BOOL bNewBehavior = FALSE;
DWORD dwBytesReturned = ;
WSAIoctl(p->socketDescriptor(), SIO_UDP_CONNRESET, &bNewBehavior, sizeof bNewBehavior, NULL, , &dwBytesReturned, NULL, NULL);
ZC: 原始套接字的获取:QUdpSocket::socketDescriptor()
4、
5、资料:
5.1、Windows UDP socket recvfrom返回10054错误的解决办法 - 朝雾之归乡 - 博客园.html(https://www.cnblogs.com/cnpirate/p/4059137.html)
现象:
在Windows 7系统上,A使用UDP socket,调用sendto函数向一个目标地址B发送数据,但是目标地址B没有接收数据,如果A此时立即调用recvfrom试图接收目标地址B发回的数据的话,recvfrom会立即返回-1,WSAGetLastError()返回10045。 原因:
上述现象是Windows socket的一个bug,当UDP Socket在某次发送后收到一个不可到达的ICMP包时,这个错误将在下一个接收中返回,所以上面的套接字在下一次的接收中返回了SOCKET_ERROR,错误是10045。 解决办法:
使用WSAIoctl设置UDP socket的工作模式,让其忽略这个错误。具体做法如下: 复制代码
#include <Winsock2.h>
#include <Mstcpip.h>
#include <stdio.h> #pragma comment(lib, "ws2_32.lib")
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12) BOOL bNewBehavior = FALSE;
DWORD dwBytesReturned = 0;
WSAIoctl(iSock, SIO_UDP_CONNRESET, &bNewBehavior, sizeof bNewBehavior, NULL, 0, &dwBytesReturned, NULL, NULL);
复制代码
SIO_UDP_CONNREST选项:Controls whether UDP PORT_UNREACHABLE messages are reported. Set to TRUE to enable reporting. Set to FALSE to disable reporting. 备注:
setsockopt是修改套接口的属性,只是该套接口在工作的过程中需要用到的一些参数;WSAIoctl则是修改套接口的工作模式,更多的定义了这个套接口要以怎样的形式进行工作,有本质的区别。
参考文献: [1]. http://blog.csdn.net/wpullo/article/details/5905616
[2]. http://msdn.microsoft.com/zh-cn/ms741621
[3]. http://blog.sina.com.cn/s/blog_536e955201009xqp.html
[4]. http://blog.csdn.net/threewall/article/details/5089817
5.2、System Error Codes (9000-11999) (Windows).html(https://technet.microsoft.com/zh-cn/ms681391(v=vs.80))
WSAECONNRESET
10054 (0x2746)
An existing connection was forcibly closed by the remote host.
5.3、System Error Codes (Windows).html(https://technet.microsoft.com/zh-cn/ms681381(v=vs.80))
6、
7、我的 VC(vs2017)测试代码:
#include <stdio.h>
#include <winsock2.h> #pragma comment(lib,"ws2_32.lib")
#define BUF_SIZE 1024
#define PORT_ 9411 int main_server(void)
{
WSADATA wsd;
int iRet = ; // 初始化套接字动态库
if (WSAStartup(MAKEWORD(, ), &wsd) != ) {
printf("WSAStartup failed:%d!\n", WSAGetLastError());
return -;
} SOCKET socketSrv = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
SOCKADDR_IN addrSrv;
SOCKADDR_IN addrClient;
char strRecv[BUF_SIZE] = { }, strSend[BUF_SIZE] = "udp server send";
int len = sizeof(SOCKADDR); // 设置服务器地址
ZeroMemory(strRecv, BUF_SIZE);
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
//addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.2.102");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(PORT_); // 绑定套接字
iRet = bind(socketSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
if (SOCKET_ERROR == iRet)
{
printf("bind failed%d!\n", WSAGetLastError());
closesocket(socketSrv);
WSACleanup();
} {
//#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12)
// BOOL bNewBehavior = FALSE;
// DWORD dwBytesReturned = 0;
// WSAIoctl(socketSrv, SIO_UDP_CONNRESET, &bNewBehavior, sizeof bNewBehavior, NULL, 0, &dwBytesReturned, NULL, NULL); SOCKADDR_IN servAddr;
servAddr.sin_family = AF_INET;
//servAddr.sin_addr.S_un.S_addr = inet_addr("192.168.0.104");
servAddr.sin_addr.S_un.S_addr = inet_addr("192.168.2.109");// _WINSOCK_DEPRECATED_NO_WARNINGS
servAddr.sin_port = htons(); // 向服务器发送数据
int nServAddLen = sizeof(servAddr);
iRet = sendto(socketSrv, strSend, BUF_SIZE, , (sockaddr *)&servAddr, nServAddLen);
if (iRet == SOCKET_ERROR) {
printf("sendto() failed:%d\n", WSAGetLastError());
closesocket(socketSrv);
WSACleanup();
return -;
}
} // 从客户端接收数据
printf("udp server start...(port:%d)\n", ntohs(addrSrv.sin_port));
while (TRUE)
{
iRet = recvfrom(socketSrv, strRecv, BUF_SIZE, , (SOCKADDR*)&addrClient, &len);
if (SOCKET_ERROR == iRet) {
int iErr = ::GetLastError();
printf("recvfrom failed ! (%d)\n", iErr);
closesocket(socketSrv);
WSACleanup();
return -;
} printf("Recv From Client:%s\n", strRecv); // 向客户端发送数据
// sendto(socketSrv, strSend, sizeof(strSend), 0, (SOCKADDR*)&addrClient, len);
} closesocket(socketSrv);
WSACleanup(); return ;
}
8、
9、
网络编程(socket).WinSocket_recvfrom出错,GetLastError()为10054的更多相关文章
- java网络编程socket\server\TCP笔记(转)
java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04| 分类: Socket | 标签:java |举报|字号 订阅 1 TCP的开销 a ...
- linux网络编程-socket(37)
在编程的时候需要加上对应pthread开头的头文件,gcc编译的时候需要加了-lpthread选项 第三个参数是线程的入口参数,函数的参数是void*,返回值是void*,第四个参数传递给线程函数的参 ...
- 网络编程socket基本API详解(转)
网络编程socket基本API详解 socket socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信. socket ...
- Android 网络编程 Socket
1.服务端开发 创建一个Java程序 public class MyServer { // 定义保存所有的Socket,与客户端建立连接得到一个Socket public static List< ...
- 网络编程Socket之TCP之close/shutdown具体解释(续)
接着上一篇网络编程Socket之TCP之close/shutdown具体解释 如今我们看看对于不同情况的close的返回情况和可能遇到的一些问题: 1.默认操作的close 说明:我们已经知道writ ...
- 铁乐学Python_Day33_网络编程Socket模块1
铁乐学Python_Day33_网络编程Socket模块1 部份内容摘自授课老师的博客http://www.cnblogs.com/Eva-J/ 理解socket Socket是应用层与TCP/IP协 ...
- Python网络编程socket
网络编程之socket 看到本篇文章的题目是不是很疑惑,what is this?,不要着急,但是记住一说网络编程,你就想socket,socket是实现网络编程的工具,那么什么是socket,什么是 ...
- python网络编程-socket编程
一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层 ...
- Python开发【第八篇】:网络编程 Socket
Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...
随机推荐
- 改变某个对象的CSS样式时,不要使用JS直接添加样式,
重绘: 使用js改变网页的背景颜色 浏览器会把整个网页的颜色重新在画一遍,导致性能降低 回流: 只要改变某个DOM对象的宽或者高,浏览器就会重新再计算网页结构,重新生成一次,导致性能严重降低. CSS ...
- JavaScript是如何工作的01:引擎,运行时和调用堆栈的概述!
概述 几乎每个人都已经听说过 V8 引擎,大多数人都知道 JavaScript 是单线程的,或者它使用的是回调队列. 在本文中,我们将详细介绍这些概念,并解释 JavaScrip 实际如何运行.通过了 ...
- 批量清理harbor镜像
#! /bin/bash # 通过Harbor提供的API来批量删除镜像,人工删除费时费力 # 经过测试发现,通过接口去删除时提供的是的标签,但实际上删除的时候通过的是镜像的IMAGE_ID,也就是说 ...
- 洛谷 P2119 魔法阵 题解
Analysis 这道题也是考试题,我也依然打了个n三次方暴力.正解是先枚举差,再枚举c和d,a和b用乘法原理优化,这样就能大大减少时间. #include<iostream> #incl ...
- CSS3 backface-visibility 不面向屏幕是否可见
backface-visibility 属性定义当元素不面向屏幕时是否可见. 如果在旋转元素不希望看到其背面时,该属性很有用. backface-visibility: visible|hidden; ...
- js的新生代垃圾回收
推荐阅读:https://www.cnblogs.com/chengxs/p/10919311.html 在进行老生代的标记清除法回收以前,还会有一个新生代的垃圾回收算法执行. 新生代和老生代 所谓新 ...
- P1095 守望者的逃离——DP?贪心?
https://www.luogu.org/problem/P1095 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变.守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大 ...
- 使用C#代码调用Web API
1. POST POST的参数需要加上[FromBady],且参数只能一个 客户端提交数据的时候ContentType 为 application/x-www-form-urlencoded 或者 a ...
- beyond compare秘钥被禁
错误提示:This license key has been revoked xxxxx 即: Windows 系统: 解决方法: 删除以下目录中的所有文件即可. C:\Users\Administr ...
- 按比例吃CPU
前几天测试软件在多核上的性能,需要按照比例吃各个CPU,查了查资料,撸了下面一小段代码: #include <unistd.h> #include <stdlib.h> #in ...