1.在connect成功建⽴立连接之后设置该选项:linger m_sLinger; m_sLinger.l_onoff = 1; // (在closesocket()调⽤用,但是还有数据没发送完毕的时候容许逗留)m_sLinger.l_linger = 0; // (容许逗留的时间为0秒)setsockopt(sockConnected, SOL_SOCKET, SO_LINGER, (const char*)&m_sLinger, sizeof(linger)); 总结 也许我们避免不了CLOSE_WAIT状态冻结的再次出现,但我们会使影响降到最⼩小,希望那个重⽤用套接字选项能够使得下⼀一次重新建⽴立连接时可以把CLOSE_WAIT状态踢掉
当使用TCP套接字时,当无网络连接时,还会继续send,继续recv阻塞,知道TCP自己协议机制判断断开连接时才会停止发送和接收,时间需要几分钟之久。 解决的办法是,自己设置接收超时时间,当超时后重新发送,或者从新初始化socket然后在重新创建socket重新connect。 代码如下:
int iSendTimeout, iRecvTimeOut; iClientSock = socket(AF_INET, SOCK_STREAM, 0); if(iClientSock < 0) { printf("[%s:%d]client init error\r\n", FILE, LINE); return ERROR; }iRecvTimeOut = 3000; iRet1 = setsockopt(iClientSock, SOL_SOCKET, SO_RCVTIMEO, &iRecvTimeOut, sizeof(int)); printf("%s\r\n", strerror(errno)); iSendTimeout = 3000; iRet2 = setsockopt(iClientSock, SOL_SOCKET, SO_SNDTIMEO, (char *)&iSendTimeout, sizeof(int)); printf("%s\r\n", strerror(errno));
但是编译会出错,perror显示参数错误(Invalid argument ),看了下内核中的实现,参数确实错了,其中最后一个参数是sizeof(struct timeval) 类型的,而非其他类型 改正为: struct timeval tv; //声明一个 struct timeval 类型的变量 然后最后个参数写为: iRet2=setsockopt(iClientSock, SOL_SOCKET, SO_SNDTIMEO, &iSendTimeout, sizeof(tv));
参数解析: int setsockopt(int s, int level, int optname,const void *optval, socklen_t optlen); 1)int s :sockfd,即socket文件描述符 2)int level : SOL_SOCKET(通用套接字) ,IPPROTO_TCP,等 3) int optname :SO_SNDTIMEO(发送超时时间)|SO_RSVTIMEO(接收超时时间)等,设置选项, 4) const void *optval :自定义的超时时间的地址 5) struct timeval的大小,即sizeof(struct timecal)
sockConnected = socket(AF_INET, SOCK_STREAM, 0);之后,我们要设置该套接字的选项来重⽤用:/// 允许重⽤用本地地址和端⼝口: /// 这样的好处是,即使socket断了,调⽤用前⾯面的socket函数也不会占⽤用另⼀一个,⽽而是始终就是⼀一个端⼝口/// 这样防⽌止socket始终连接不上,那么按照原来的做法,会不断地换端⼝口。 int nREUSEADDR = 1;setsockopt(sockConnected,SOL_SOCKET, SO_REUSEADDR,(const char*)&nREUSEADDR, sizeof(int));
WSAEINTR (10004)
转换 : 中断函数调用。说明 : 阻止的操作已被对 WSACancelBlockingCall (Wsapiref_704y.asp) 的调用中断。
WSAEACCES (10013)
转换 : 被拒绝的权限。说明 : 一个试图访问已禁止其访问权限的套接字。 是例如此错误时发生了广播的地址用于 Sendto 但广播权限不通过 setsockopt(SO_BROADCAST) 设置的。 WSAEACCES 错误的另一个可能原因是,绑定 (Wsapiref_6vzm.asp) 函数调用时 (在 Microsoft Windows NT 4.0 Service Pack 4 [SP 4] 或更高版本),另一个程序、 服务或内核模式驱动程序绑定到以独占访问相同的地址。 独占访问是一项新功能的 Windows NT 4.0 SP 4 及更高版本中,并它实现使用 SO_EXCLUSIVEADDRUSE 选项。
WSAEFAULT (10014)
转换 : 错误的地址。说明 : 尝试使用调用的一个指针参数时 -系统检测到无效指针地址。 如果程序传递了无效的指针值,或者如果缓冲区的长度太小会发生此错误。 是例如如果 SOCKADDR 结构的参数的长度小于 sizeof(SOCKADDR) 值,则会出现此问题。
WSAEINVAL (10022)
转换 : 无效的参数。说明 : 一个无效参数 (而是例如的参数指定了无效的级别) 提供给 setsockopt (Wsapiref_94aa.asp) 函数。 有时,它还引用此套接字的当前状态,调用套接字未侦听上接受 (Wsapiref_13aq.asp) 的是例如。
WSAEMFILE (10024)
转换 : 打开的文件太多。说明 : 有太多打开的套接字。 每个实现可能会有可用的套接字处理一个最大数量。 这些句柄可能全局,每进程,或每线程。
WSAEWOULDBLOCK (10035)
转换 : 资源暂时不可用。说明 : 此返回错误无法完成的立即,是例如 nonblocking 套接字操作 recv (Wsapiref_2i9e.asp),无数据排队从套接字读取时。 一个非致命的错误和操作可以稍后重试。 WSAEWOULDBLOCK 通常报告为已调用的结果 nonblocking SOCK_STREAM 套接字连接 (Wsapiref_8m7m.asp),因为一些时间必须经过建立连接。
WSAEINPROGRESS (10036)
转换 : 正在进行的操作。说明 : 阻止操作当前正在运行。 Windows 套接字仅允许一次的阻止操作,为每个任务或每个线程为未完成。 如果 (无论它引用或任何其他套接字) 进行任何其他函数调用,则操作将失败 WSAEINPROGRESS 错误。
WSAEALREADY (10037)
转换 : 已在进行的操作。说明 : 已进行的操作后,尝试一个操作 nonblocking 套接字上。 是例如电话连接 (Wsapiref_8m7m.asp) 一个 nonblocking 套接字已连接的尝试第二次的或异步请求 (WSAAsyncGetXbyY) 曾已取消或完成。
WSAENOTSOCK (10038)
转换 : 套 nonsocket 操作。说明 : 一个操作已尝试在不套接字的。 套接字句柄参数引用一个有效的套接字,或者选择 (Wsapiref_1ab6.asp),一个 fd_set 的成员是无效。
WSAEDESTADDRREQ (10039)
转换 : 所需的目标地址。说明 : 从套接字上的操作中省略一个所需的地址时。 是例如如果 Sendto (Wsapiref_4sqa.asp) 的远程地址 ADDR_ANY 调用将返回此错误。
WSAEMSGSIZE (10040)
转换 : 邮件太长。说明 : 发送数据报套接字上的一封邮件大于内部消息缓冲区或其他一些网络限制或者用于接收数据报的缓冲区比其自身数据报小。
WSAEPROTOTYPE (10041)
转换 : 协议的套接字的错误类型。说明 : 套接字 (Wsapiref_2qr6.asp) 函数调用中指定一个协议不支持请求的套接字类型的语义。 是例如 SOCK_STREAM 套接字类型不能指定 ARPA Internet UDP 协议。
WSAENOPROTOOPT (10042)
转换 : 错误的协议选项。说明 : getsockopt (Wsapiref_8qcy.asp) 调用或 setsockopt (Wsapiref_94aa.asp) 调用中指定一个未知、 无效,或不支持选项或级别。
WSAEPROTONOSUPPORT (10043)
转换 : 不支持的协议。说明 : 程序请求的协议没或者被配置为在系统中,或者没有实现为其存在。 例如,套接字 (Wsapiref_2qr6.asp) 调用请求 SOCK_DGRAM 套接字,但它指定一个流协议。
WSAESOCKTNOSUPPORT (10044)
转换 : 套类型不受支持。说明 : -支持指定的套接字类型不在此地址系列。 是例如 SOCK_RAW 可选类型可以选择在套接字 (Wsapiref_2qr6.asp) 调用,但实现根本不支持 SOCK_RAW 套接字。
WSAEOPNOTSUPP (10045)
转换 : 不支持的操作。说明 : 已尝试该操作不支持引用的对象的类型。 到不支持此操作的套接字的套接字描述符试图接受数据报套接字上的连接时通常出现此错误。
WSAEPFNOSUPPORT (10046)
转换 : 协议系列不受支持。说明 : The 协议家族尚未配置系统中,或者没有实现为其存在。 此邮件有从 WSAEAFNOSUPPORT 某种稍有不同的含义。 但是,是经常互换。 返回这些消息之一的所有 Windows 套接字功能还都指定 WSAEAFNOSUPPORT。
WSAEAFNOSUPPORT (10047)
转换 : 地址家族不受协议系列。说明 : 使用一个与请求的协议不兼容的地址。 所有的套接字创建具有一个关联的地址族 (这就是对 Internet 协议的 AF_INET) 和泛型的协议类型 (这就是 SOCK_STREAM)。 如果套接字 (Wsapiref_2qr6.asp) 调用显式请求的不正确的协议,或者 Sendto (Wsapiref_4sqa.asp) 中在错误的系列地址使用的一个的套接字是例如,将返回此错误。
WSAEADDRINUSE (10048)
转换 : 已在使用中的地址。说明 : 允许每个套接字地址 (协议 / IP 地址 / 端口) 的只有一个使用的通常。 如果某个程序试图绑定 Wsapiref_6vzm.asp 到一个 IP 地址或端口已被使用的一个现有的套接字套接字未正确,关闭套接字就会发生此错误或套接字的仍在过程结束。 对于绑定到相同的端口号的多个套接字的服务器程序请考虑使用 Setsockopt (Wsapiref_94aa.asp)(SO_REUSEADDR)。 客户端程序通常没有在调用绑定、 连接 (Wsapiref_8m7m.asp) 自动选择一个未使用的端口。 绑定调用使用通配符地址 (包括 ADDR_ANY) 时, 提交特定地址之前可能延迟了 WSAEADDRINUSE 错误。 这可能会出现更高版本,包括连接、 侦听、 WSAConnect 或 WSAJoinLeaf 的另一个函数调用。
WSAEADDRNOTAVAIL (10049)
转换 : 无法分配请求的地址。说明 : The 请求的地址是其上下文中的无效。 此错误通常到本地计算机的无效地址导致试图绑定 (Wsapiref_6vzm.asp)。 此错误也导致从连接 (Wsapiref_8m7m.asp),Sendto (Wsapiref_4sqa.asp),WSAConnect (Wsapiref_8kc2.asp)、 WSAJoinLeaf (Wsapiref_7dv6.asp) 或 WSASendTo (Wsapiref_752q.asp) 如果远程地址或端口为远程计算机 (for example,地址或端口 0) 的无效。
WSAENETDOWN (10050)
转换 : 网络已关闭。说明 : A 套接字操作遇到死的网络。 此错误可能表示网络系统 (这就是该协议堆栈上运行的 Windows 套接字 DLL 的)、 网络界面或本地网络本身在严重发生故障。
WSAENETUNREACH (10051)
转换 : 网络不可访问。说明 : A 套接字操作尝试一个无法访问网络。 此错误通常表示本地软件知道到达远程主机没有路由。
WSAENETRESET (10052)
转换 : 网络上重置丢弃连接。说明 : The 连接中断由于的在操作过程中检测到错误的保持连接活动。 它可以也由返回 setsockopt (Wsapiref_94aa.asp) 如果试图对已失败的连接设置 SO_KEEPALIVE。
WSAECONNABORTED (10053)
转换 : 软件导致连接暂停。说明 : 一个建立的连接停止您的主机该软件可能会因数据传输超时或协议错误。
WSAECONNRESET (10054)
转换 : 通过对等方重置的连接。说明 : 一个现有的连接被远程主机强制关闭。 如果远程主机上的对等程序突然停止、 主机重新启动或远程主机使用硬盘的关闭则,通常会发生此错误。 有关详细信息,有关远程套接字上 SO_LINGER 选项,请参阅 Setsockopt (Wsapiref_94aa.asp)。 如果由于的正在进行一个或多个操作时检测到错误的保持连接活动的连接已断开,也可能会导致此错误。 在进行的操作失败,并 WSAENETRESET。 随后的操作失败,出现 WSAECONNRESET。
WSAENOBUFS (10055)
转换 : 无可用的缓冲区空间。说明 : 由于系统缺少缓冲区空间不足或队列已满,无法执行套接字上的一个操作。
WSAEISCONN (10056)
转换 : 套接字已连接。说明 : 一个已连接的套接字上发出一个连接请求。 如果 Sendto (Wsapiref_4sqa.asp) 调用连接 SOCK_DGRAM 套接字上某些实现也返回此错误 (为 SOCK_STREAM 套接字,在 Sendto 中参数 (Wsapiref_4sqa.asp) 将被忽略) 尽管其他实现将此视为有效的事件。
WSAENOTCONN (10057)
转换 : 套接字未连接。说明 : 因为套接字未连接并且 (发送数据报套接字使用 Sendto [Wsapiref_4sqa.asp] 上时, 没有地址提供),不允许一个请求发送或接收数据。 任何其他类型的操作也可能会返回此错误,例如如果连接重置设置 SO_KEEPALIVE setsockopt (Wsapiref_94aa.asp)。
WSAESHUTDOWN (10058)
转换 : 套接字关闭后无法发送。说明 : 因为套接字必须已被关闭在该方向上一个关闭 (Wsapiref_60z6.asp) 调用一个请求发送或接收数据时不允许。 关闭调用时, 请求的套接字的部分关闭。 这是已停止发送或接收进程 (或两者) 的信号。
WSAETIMEDOUT (10060)
转换 : 连接超时。说明 : 由于连接的方没有不正确响应时间,一段时间后或建立的连接失败,因为响应失败的连接的主机 A 的连接尝试失败。
WSAECONNREFUSED (10061)
转换 : 连接被拒绝。说明 : 无连接可建立,因为目标计算机积极地拒绝。 此错误通常导致尝试连接到处于非活动状态这就是指没有服务器程序运行在外部主机上的服务。
WSAEHOSTDOWN (10064)
转换 : 主机已关闭。说明 : A 的套接字操作失败,因为目标主机已关闭。 套接字操作遇到死主机。 本地主机的网络活动已被初始化。 这些情况更有可能由错误 WSAETIMEDOUT。
WSAEHOSTUNREACH (10065)
转换 : 无路由主机。说明 : A 套接字操作已尝试到无法访问主机。 请参阅 WSAENETUNREACH。
WSAEPROCLIM (10067)
转换 : 太多进程。说明 : 一个 Windows 套接字实现可能会限制的程序,可以使用在同一时间数。 如果在达到该限制,WSAStartup (Wsapiref_1v8y.asp) 可能会因此错误。
WSASYSNOTREADY (10091)
转换 : 网络子系统不可用。说明 : 如果 Windows 套接字实现当前无法工作,因为它用来提供网络服务的基础系统当前不可用的 WSAStartup (Wsapiref_1v8y.asp) 会返回此错误。 确认以下几点: 请确认相应的 Windows 套接字 DLL 文件位于当前路径。 请确认它们没有试图在同一时间使用多个 Windows 套接字实现。 如果有多个 Winsock DLL 在系统上,请确认路径中第一个的 Winsock DLL 是适用于当前加载网络子系统。 确认所有必需的组件是当前安装并正确配置根据为 Windows 套接字实现文档。
WSAVERNOTSUPPORTED (10092)
转换 : Winsock.dll 版本出范围。说明 : The 当前的 Windows 套接字实现不支持 Windows 套接字规范版本请求程序。 请确保访问任何旧的 Windows 套接字 DLL 文件。
WSANOTINITIALISED (10093)
转换 : 成功 WSAStartup 尚未执行。说明 : Either 程序具有不称为 WSAStartup (Wsapiref_1v8y.asp) 或 WSAStartup (Wsapiref_1v8y.asp) 失败。 该程序可能正在访问套接字不拥有当前的活动任务 (这就正在尝试进行共享的任务之间套接字),或 WSACleanup 已调用多次。
WSAEDISCON (10101)
转换 : 正在正常关闭。说明 : 由 WSARecv (Wsapiref_4z1u.asp) 和 WSARecvFrom (Wsapiref_4wky.asp),指示远程方已启动正常的关闭序列中返回此错误。
WSATYPE_NOT_FOUND (10109)
转换 : 类找不到的类型。说明 : 找不到程序指定的类。
WSAHOST_NOT_FOUND (11001)
转换 : 找不到主机。 不称为任何这样的主机。说明 : -名不是正式的主机名或别名,或它无法找到正在查询的数据库中。 此错误可能还返回为协议和服务查询,并且这意味着在相关数据库中无法找到指定的名称。
WSATRY_AGAIN (11002)
转换 : 找不到非授权主机。说明 : 此错误是通常在临时错误主机名称解析,期间,它意味着本地服务器从权威服务器是否未收到响应。 在稍后某个时间重试可能成功。
WSANO_RECOVERY (11003)
转换 : 这是一个 nonrecoverable 的错误。说明 : 此错误表示某种 nonrecoverable 错误发生在数据库查找。 如果找不到数据库文件 (是例如 BSD 兼容 HOSTS、 SERVICES 或协议文件),或者如果 DNS 请求返回了一个严重错误服务器,可能会出现此错误。
WSANO_DATA (11004)
转换 : 有效的名称、 请求类型的任何数据记录。说明 : 程序请求的名称是有效但中找到在的数据库,但它没有正确的解决的它的相关的数据。 为此,典型示例是对主机名称到地址转换尝试 (使用 gethostbyname [Wsapiref_0q5u.asp] 或 WSAAsyncGetHostByName [Wsapiref_7bhu.asp]) 使用 DNS 服务器。 但没有 A 记录,则返回的 MX 记录。 这指示其自身主机存在,但不是直接可到达。
WSA_INVALID_HANDLE (依赖于操作系统)
转换 : 指定事件对象句柄无效。说明 : 一个程序试图使用 Event 对象,但是指定的句柄是无效。
WSA_INVALID_PARAMETER (依赖于操作系统)
转换 : 一个或多个参数是无效。说明 : 一个程序使用一个 Windows 套接字函数,直接将映射到 Win 32 函数。 Win 32 函数指示一个或多个参数有问题。
WSA_IO_INCOMPLETE (依赖于操作系统)
转换 : 重叠的 I / O 事件对象不在信号状态。说明 : The 程序已尝试确定尚未完成的重叠操作的状态。 在操作完成之前,确定重叠的操作完成的时间在轮询模式下使用 WSAGetOverlappedResult (带有 fwait 标志集为 FALSE) 的程序收到此错误代码。
WSA_IO_PENDING (依赖于操作系统)
转换 : 重叠的操作将在以后完成。说明 : The 程序已开始的重叠的操作,无法立即完成的。 在操作完成时,将更高版本发送完成指示。
WSA_NOT_ENOUGH_MEMORY (依赖于操作系统)
转换 : 不足的内存。说明 : 一个程序使用一个 Windows 套接字函数,直接将映射到 Win 32 函数。 Win 32 函数指示所需的内存资源不足。
WSA_OPERATION_ABORTED (依赖于操作系统)
转换 : 覆盖操作被终止。说明 : 由于套接字已关闭,或 WSAIoctl (Wsapiref_6ik2.asp) 中的 SIO_FLUSH 命令已运行,出现重叠的操作被取消。
WSAINVALIDPROCTABLE (依赖于操作系统)
转换 : 无效的过程表服务提供商。说明 : 服务提供程序返回到 Ws2_32.dll 的一个无效的过程表。 (这是通常所致一个或多个在空的函数指针)。
WSAINVALIDPROVIDER (依赖于操作系统)
转换 : 无效的服务提供程序的版本号。说明 : 服务提供程序返回以外 2.0 的版本号。
WSAPROVIDERFAILEDINIT (依赖于操作系统)
转换 : 无法初始化服务提供程序。说明 : Either 服务提供商的 DLL 无法加载 (LoadLibrary 失败),或提供程序的 WSPStartup / NSPStartup 函数失败。
WSASYSCALLFAILURE (依赖于操作系统)
转换 : 系统调用失败。说明 : 永远不会将失败的系统调用失败时,将返回此错误。 是例如如果对 WaitForMultipleObjects 的调用失败,或者其中一个注册表函数失败尝试更改协议或名称空间目录,则会发生此错误。