Winsock错误10048说明

背景:

最近在做网络IO模型时,遇到一个问题,客户端软件连接服务器端一次断开以后,很长一段时间以内不能连接第二次。后来发现,客户端(Windows)同一个端口的socket在close以后的两分钟内Windows是没有释放这个handle的,所以才会出现bind->connect失败。WSAGetLastError()返回10048错误。

10048:通常每个套接字地址(协议/网络地址/端口)只允许使用一次。

问题相关:

MSDN的说明如下: 

这种错误常常发生在bind函数中,当bind已经绑定的端口被占用后,再次绑定同一端口就会发生错误,但这一错误不影响bind的执行,换句话说,bind第二次执行并不发生错误,但是在紧接着调用connect()时会出错,错误码就是10048。    

应用程序调用bind在使用随机端口绑定时,如果操作系统预留的1024~5000之间的端口都被占用着的话,bind不出错,connect会失败。

 什么情况下端口会被全部占用?      

      情况一:如果每个端口上都正在进行数据操作,那么端口就都处于占用状态。          

      情况二:connect的频率太快,每一个socket在调用closesocket进行关闭操作后,虽然closesocket执行完毕,但是对应的占用端口并不是立即释放,这些端口需要继续处于占用状态,等待时间大约2ML(数据包最大生存周期),默认最大值为4分钟。用netstat命令查看端口状态,端口显示TIME_WAIT,在4分钟内如果对同一个端口进行connect,就会发生10048错误。     

说明:

新版的客户端在登录的时候与服务器进行连接的时候socket有bind固定的端口(旧版本没有bind固定端口,之所以这样做是因为之前你们反应登录的时候会出现用户已经登录的情况,经过与服务器端商量才决定这样的)。

在Windows下,系统会将每个连接(包含已经被关闭的连接)所占用的端口维持2个TTL(约120s),才进行资源释放进行下次使用。

也许你会问为什么不是每次出现10048的错误,原因一有可能是你连续登录的时间已经超过120S,原因二有可能是客户端logout VMS的时候VMS先将之前的链接关闭。

还有之前为什么不会出现10048的错误,是因为之前客户端socket没有绑定固定端口,而是由windos随机分配的端口,这样出现10048错误的概率就大大降低。 但是Windows限制本地端口总数为5000个,我们做测试可以发现如果连续不停的connect当windows将5000个端口都用完的话再connect也会出现10048的错误。

解决办法:

1.由Windos随机分配未使用的端口

addr.sin_port = 0;        // 若port指定为0,则调用bind时,系统会为其指定一个可用的端口号

2. 如果使用了bind函数,那么可以对绑定的端口进行指定,如果调用connect失败,那么就返回bind处更改绑定端口,然后继续connect,直到成功为止。     

3.如果没有使用bind函数,直接使用connect进行连接,那么可以对connect操作进行retry,在这种情况下如果connect失败,那么它下次被调用时仍会使用调用失败的端口进行连接,直到连接成功。

 

随机获取一个可用的端口号

思路: 将一个socket 绑定到本机,使用getsockname获取此socket关联的端口号

函数声明:

bool getAvaliablePort(unsigned short &port);
                               // 返回:若成功则为true, 否则为false
* @brief 获取可用的端口
 *
 * @param port : 输出,返回可用的端口号
 *
 * @return 若成功则返回true,否则放回false
 */
bool getAvaliablePort(unsigned short &port)
{
    bool result = true;

    // 1. 创建一个socket
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);

    // 2. 创建一个sockaddr,并将它的端口号设为0
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(ADDR_ANY);
    addr.sin_port = 0;        // 若port指定为0,则调用bind时,系统会为其指定一个可用的端口号

    // 3. 绑定
    int ret = bind(sock, (SOCKADDR*)&addr, sizeof addr);

    if (0 != ret) {
        result = false;
        goto END;
    }

    // 4. 利用getsockname获取
    struct sockaddr_in connAddr;
    int len = sizeof connAddr;
    ret = getsockname(sock, (SOCKADDR*)&connAddr, &len);

    if (0 != ret){
        result = false;
        goto END;
    }

    port = ntohs(connAddr.sin_port); // 获取端口号

END:
    if ( 0 != closesocket(sock) )
        result = false;
    return result;
}

参考:https://www.cnblogs.com/hdtianfu/archive/2012/10/20/2732675.html

           https://blog.csdn.net/qq_17242957/article/details/43053961

           https://bbs.csdn.net/topics/390292355

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows Sockets网络编程》是WindowsSockets网络编程领域公认的经典著作,由Windows Sockets2.0规范解释小组负责人亲自执笔,权威性毋庸置疑。它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是学习WindowsSockets网络编程不可多得的参考书。   全书分为三部分:第一部分(第1~6章),提供了翔实的背景知识和框架方面的概念,借助于此框架,读者可理解WinSock的具体细节,包括WindowsSockets概述、OSI网络参考模型、TCP/IP协议簇中的协议和可用的服务、WinSock网络应用程序的框架及其工作机制、WinSock的三种操作模式、socket通信机制等;第二部分(第7~12章),以FTP客户端实例为基础介绍了函数实例库,还介绍了客户端程序、服务器程序和DLL中间构件及它们的相应函数,并涵盖socket命令和选项及移植BSDSockets相关事项等;第三部分(第13~17章),介绍了应用程序调试技术和工具,针对应用编程中的陷阱的建议和措施,WinSockAPI的多种操作系统平台,WinSock规范的可选功能和WinSock规范2.0中的所有新功能。 译者序 序 前言 第1章 Windows Sockets概述 1.1 什么是Windows Sockets 1.2 Windows Sockets的发展历史 1.3 Windows Sockets的优势 1.3.1 Windows Sockets是一个开放的标准 1.3.2 Windows Sockets提供源代码可移植性 1.3.3 Windows Sockets支持动态链接 1.3.4 Windows Sockets的优点 1.4 Windows Sockets的前景 1.5 结论 第2章 Windows Sockets的概念 2.1 OSI网络模型 2.2 WinSock网络模型 2.2.1 信息与数据 2.2.2 应用协议 2.3 WinSock中的OSI层次 2.3.1 应用层 2.3.2 表示层 2.3.3 会话层 2.3.4 传输层 2.3.5 网络层 2.3.6 数据链路层 2.3.7 物理层 2.4 模块化的层次框 2.5 服务和协议 2.6 协议和API 第3章 TCP/IP协议服务 3.1 什么是TCP/IP 3.2 TCP/IP的发展历史 3.3 传输服务 3.3.1 无连接的服务:UDP 3.3.2 面向连接的服务:TCP 3.3.3 传输协议的选择:UDP与TCP的对比 3.4 网络服务 3.4.1 IP服务 3.4.2 ICMP服务 3.5 支持协议和服务 3.5.1 域名服务 3.5.2 地址解析协议 3.5.3 其他支持协议 3.6 TCP/IP的发展前景 第4章 网络应用程序工作机制 4.1 客户端-服务器模型 4.2 网络程序概览 4.3 socket的打开 4.4 socket的命名 4.4.1 sockaddr结构 4.4.2 sockaddr_in结构 4.4.3 端口号 4.4.4 本地IP地址 4.4.5 什么是socket名称 4.4.6 客户端socket名称是可选的 4.5 与另一个socket建立关联 4.5.1 服务器如何准备建立关联 4.5.2 客户端如何发起一个关联 4.5.3 服务器如何完成一个关联 4.6 socket之间的发送与接收 4.6.1 在“已连接的”socket上发送数据 4.6.2 在“无连接的”socket上发送数据 4.6.3 接收数据 4.6.4 socket解复用器中的关联 4.7 socket的关闭 4.7.1 closesocket 4.7.2 shutdown 4.8 客户端和服务器概览 第5章 操作模式 5.1 什么是操作模式 5.1.1 不挂机,等待:阻塞 5.1.2 挂机后再拨:非阻塞 5.1.3 请求对方回拨:异步 5.2 阻塞模式 5.2.1 阻塞socket 5.2.2 阻塞函数 5.2.3 伪阻塞的问题 5.2.4 阻塞钩子函数 5.2.5 阻塞情境 5.2.6 撤销阻塞操作 5.2.7 阻塞操作中的超时 5.2.8 无最少接收限制值 5.2.9 代码示例 5.3 非阻塞模式 5.3.1 怎样使socket成为非阻塞的 5.3.2 成功与失败不是绝对的 5.3.3 探询而非阻塞 5.3.4 显式地避让 5.3.5 代码示例 5.4 异步模式 5.4.1 认识异步函数 5.4.2 撤销异步操作 5.4.3 代码示例 5.4.4 AU_T
说明: 1此程序由ecz00程序优化而来 地址 http://download.csdn.net/download/ecz00/9403630 因此程序可以说是网上唯一的tcpclient使用的中文案例,提供了我思路,在此感谢 ;为什么用这个插件,vb自带的插件winsock 这么有用的插件 居然不是微软自带的插件, 最要命的是 直接注册ocx控件 win7 win10上可能因为序列号无法注册,那么vb下如何开发ip客户端,变得很麻烦,尝试过APi方法的,但是过于复杂,程序量太大,比较麻烦,因此用 此方案比较可行,在原版的基础上花了5天时间摸索和优化, 此版本使用方法 1 把vbRichClient5.dll放进C:\Windows\SysWOW64 (64位系统) 2 在vb6中点击 工程->引用 把上面的dll引用进来就可以额,不需要注册 3:使用sscom5.12.1 或其他tcp调试软件软件启动tcpserver 地址是127,0,0,1 5676 4:直接运行本软件即可使用。点击连接,显示成功,说明连接成功,可以相互发送数据了 服务端的程序在原版上未做修改,请自行优化 此软件改进了原版 1:无法显示连接状态和错误信息 2:只能发送不能接收 3:使用主机名的连接方式,无法直接使用,一开始 4:无法显示byte值 5:界面修改 6:连接的时候,不断开以前的连接,造成重复连接 提示 vbRichClient5的手册找遍了都找不到,估计作者都没写,更别想有中文版了,所以只能 在vb6中点击视图-》对象窗口,可显示vbRichClient5.dll 所有的类和方法 QQ175891641 2018-2-15优化
Windows Sockets网络编程》是WindowsSockets网络编程领域公认的经典著作,由Windows Sockets2.0规范解释小组负责人亲自执笔,权威性毋庸置疑。它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是学习WindowsSockets网络编程不可多得的参考书。   全书分为三部分:第一部分(第1~6章),提供了翔实的背景知识和框架方面的概念,借助于此框架,读者可理解WinSock的具体细节,包括WindowsSockets概述、OSI网络参考模型、TCP/IP协议簇中的协议和可用的服务、WinSock网络应用程序的框架及其工作机制、WinSock的三种操作模式、socket通信机制等;第二部分(第7~12章),以FTP客户端实例为基础介绍了函数实例库,还介绍了客户端程序、服务器程序和DLL中间构件及它们的相应函数,并涵盖socket命令和选项及移植BSDSockets相关事项等;第三部分(第13~17章),介绍了应用程序调试技术和工具,针对应用编程中的陷阱的建议和措施,WinSockAPI的多种操作系统平台,WinSock规范的可选功能和WinSock规范2.0中的所有新功能。 译者序 序 前言 第1章 Windows Sockets概述 1.1 什么是Windows Sockets 1.2 Windows Sockets的发展历史 1.3 Windows Sockets的优势 1.3.1 Windows Sockets是一个开放的标准 1.3.2 Windows Sockets提供源代码可移植性 1.3.3 Windows Sockets支持动态链接 1.3.4 Windows Sockets的优点 1.4 Windows Sockets的前景 1.5 结论 第2章 Windows Sockets的概念 2.1 OSI网络模型 2.2 WinSock网络模型 2.2.1 信息与数据 2.2.2 应用协议 2.3 WinSock中的OSI层次 2.3.1 应用层 2.3.2 表示层 2.3.3 会话层 2.3.4 传输层 2.3.5 网络层 2.3.6 数据链路层 2.3.7 物理层 2.4 模块化的层次框 2.5 服务和协议 2.6 协议和API 第3章 TCP/IP协议服务 3.1 什么是TCP/IP 3.2 TCP/IP的发展历史 3.3 传输服务 3.3.1 无连接的服务:UDP 3.3.2 面向连接的服务:TCP 3.3.3 传输协议的选择:UDP与TCP的对比 3.4 网络服务 3.4.1 IP服务 3.4.2 ICMP服务 3.5 支持协议和服务 3.5.1 域名服务 3.5.2 地址解析协议 3.5.3 其他支持协议 3.6 TCP/IP的发展前景 第4章 网络应用程序工作机制 4.1 客户端-服务器模型 4.2 网络程序概览 4.3 socket的打开 4.4 socket的命名 4.4.1 sockaddr结构 4.4.2 sockaddr_in结构 4.4.3 端口号 4.4.4 本地IP地址 4.4.5 什么是socket名称 4.4.6 客户端socket名称是可选的 4.5 与另一个socket建立关联 4.5.1 服务器如何准备建立关联 4.5.2 客户端如何发起一个关联 4.5.3 服务器如何完成一个关联 4.6 socket之间的发送与接收 4.6.1 在“已连接的”socket上发送数据 4.6.2 在“无连接的”socket上发送数据 4.6.3 接收数据 4.6.4 socket解复用器中的关联 4.7 socket的关闭 4.7.1 closesocket 4.7.2 shutdown 4.8 客户端和服务器概览 第5章 操作模式 5.1 什么是操作模式 5.1.1 不挂机,等待:阻塞 5.1.2 挂机后再拨:非阻塞 5.1.3 请求对方回拨:异步 5.2 阻塞模式 5.2.1 阻塞socket 5.2.2 阻塞函数 5.2.3 伪阻塞的问题 5.2.4 阻塞钩子函数 5.2.5 阻塞情境 5.2.6 撤销阻塞操作 5.2.7 阻塞操作中的超时 5.2.8 无最少接收限制值 5.2.9 代码示例 5.3 非阻塞模式 5.3.1 怎样使socket成为非阻塞的 5.3.2 成功与失败不是绝对的 5.3.3 探询而非阻塞 5.3.4 显式地避让 5.3.5 代码示例 5.4 异步模式 5.4.1 认识异步函数 5.4.2 撤销异步操作 5.4.3 代码示例 5.4.4 AU_T

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值