网络编程(socket).WinSocket_recvfrom出错,GetLastError()为10054

摘要:
2.3.在Qt中设置后,不存在上述现象。3.1.Qt中的设置:#defineISIO_UDP_CONNRESET_WSAIOWBOOLbNewBehavior=FALSE;DWORDdwBytesReturned=0;WSAIoctl;ZC:获取原始套接字:QUdpSocket::socketDescriptor()4,5。数据:5.1。Windows UDP套接字recvfrom返回10054错误。解决方案-迷雾之家-博客花园Html现象:在Windows7系统上,A使用UDP套接字调用sendto函数将数据发送到目标地址B,但目标地址B不接收数据。如果A立即调用recvfrom以尝试接收从目标地址B发送的数据,recvfrom将立即返回-1,WSAGetLastError()将返回10045。

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 = 0;
WSAIoctl(p->socketDescriptor(), SIO_UDP_CONNRESET, &bNewBehavior, sizeof bNewBehavior, NULL, 0, &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 = 0;

    // 初始化套接字动态库
    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
        printf("WSAStartup failed:%d!
", WSAGetLastError());
        return -1;
    }

    SOCKET socketSrv = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    SOCKADDR_IN addrSrv;
    SOCKADDR_IN addrClient;
    char strRecv[BUF_SIZE] = { 0 }, 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!
", 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(9418);

        // 向服务器发送数据
        int nServAddLen = sizeof(servAddr);
        iRet = sendto(socketSrv, strSend, BUF_SIZE, 0, (sockaddr *)&servAddr, nServAddLen);
        if (iRet == SOCKET_ERROR) {
            printf("sendto() failed:%d
", WSAGetLastError());
            closesocket(socketSrv);
            WSACleanup();
            return -1;
        }
    }

    // 从客户端接收数据
    printf("udp server start...(port:%d)
", ntohs(addrSrv.sin_port));
    while (TRUE)
    {
        iRet = recvfrom(socketSrv, strRecv, BUF_SIZE, 0, (SOCKADDR*)&addrClient, &len);
        if (SOCKET_ERROR == iRet) {
            int iErr = ::GetLastError();
            printf("recvfrom failed ! (%d)
", iErr);
            closesocket(socketSrv);
            WSACleanup();
            return -1;
        }

        printf("Recv From Client:%s
", strRecv);

        // 向客户端发送数据
    //    sendto(socketSrv, strSend, sizeof(strSend), 0, (SOCKADDR*)&addrClient, len);
    }

    closesocket(socketSrv);
    WSACleanup();

    return 0;
}

8、

9、

免责声明:文章转载自《网络编程(socket).WinSocket_recvfrom出错,GetLastError()为10054》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇jQuery.Switchable 1.0特征分解 奇异值分解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

IOS网络编程之Socket详解

Socket描述了一个IP、端口对。它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息。所以,Socket一定包含了通信的双发,即客户端(Client)与服务端(server)。1)服务端利用Socket监听端口;2)客户端发起连接;3)服务端返回信息,建立连接,开始通信;4)客户端,服务端断开连接。 1...

Socket的双网卡收发(C#)

最近的一个项目中需要同时使用两块网卡收发UDP组播数据包,并且要求使用Socket的方式接收和发送网络数据包(我不会告诉你们我之前是直接使用SharpPcap来实现的)。在C#中Socket接触的比较早,但是用的不多,特别是在实现本次上网卡的收发过程中也是遇到了不少麻烦。其中最最头疼的就是不能同时接收两张网卡的数据,虽然这个问题不是致命的(大不了用Shar...

Java高并发网络编程(五)Netty应用

推送系统 一、系统设计 二、拆包和粘包 粘包、拆包表现形式 现在假设客户端向服务端连续发送了两个数据包,用packet1和packet2来表示,那么服务端收到的数据可以分为三种,现列举如下: 第一种情况,接收端正常收到两个数据包,即没有发生拆包和粘包的现象,此种情况不在本文的讨论范围内。 第二种情况,接收端只收到一个数据包,由于TCP是不会出现丢包的...

Linux的SOCKET编程详解

Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统。由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如 UNIX BSD有:管道(pipe)、命名管道(named pipe)软中断信号(signal) UNIX syste...

DLNA介绍(包含UPnP,2011/6/20 更新)

这部分的内容大多来源于网络及官方文档,依照自己的翻译理解整理所成。东西比較多,从头慢慢看还是能够懂个大概的。 文件夹: 一、DNLA的建立 二、DLNA的成员 三、DLNA标准的制定 四、DLNA的设备 五、DLNA的架构 六、云时代的数字家庭(待填坑) 扩展阅读I: UPnP的工作过程------------DLNA基础协议框架 扩展阅读II UPnP...

详解tomcat的连接数与线程池

前言 在使用tomcat时,经常会遇到连接数、线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector)。 在前面的文章详解Tomcat配置文件server.xml中写到过:Connector的主要功能,是接收连接请求,创建Request和Response对象用于和请求端交换数据;然后分配线程让Engine(也就是Ser...