Error -27740: WSA_IO_pending

本文探讨了LoadRunner中遇到的WSA_IO_PENDING错误及解决方法。通过禁用First Buffer分解,采用同步发送方式,减少上下文切换,有效避免了连接过早关闭的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Error -27740: WSA_IO_pending
Action.c(198): Error -27791: Server **** has shut down the connection prematurely
Action.c(198): Error -27790: Failed to read data from server  *** [10053] Software caused connection abort
Action.c(198): Error -27740: Overlapped transmission of request to"www.****"  for URL "****"  failed: WSA_IO_PENDING

 
Diagnosis: 
    Overlapped transmission of request to '%1' for URL 'URL' failed. The transmission of data to the server failed. It could be a network, router, or server problem. The word Overlapped refers to the way LoadRunner sends data in order to get a Web Page Breakdown.
--------- Troubleshooting-----------------------------------
    Add the following statement to the beginning of the script to disable the breakdown of the "First Buffer" into server and network time: 

    web_set_sockets_option("OVERLAPPED_SEND", "0");
 
--------- 经验------------------------------------------------------------------------
IO Overlapped是一种异步IO,在socket层,只有少量数据发送的时候,只要create new thread,send, receive就可以。
但是当数据量增加的时候,要考虑资源的充分利用,也要避免资源的拥塞队列,如果创建线程过多,和CPU内存磁盘等资源的交互过多,可能导致拥塞出现。在这时就要考虑资源的拥塞问题了,在socket中有两种处理的方式:

1.IO overlapped
工作方式是这样的:
A:调用WSARecv, WSARecvFrom, WSASend, WSASendTo, 或 WSAIoctl.等函数,传入overlapped参数,表示这个函数要执行这个动作;
B:调用WSAGetOverlappedResult函数来取数据;
C:再执行A,调用另一个带有overlapped的参数另一个线程交替处理。
这种方式,可以处理一定量的数据。但是在大数据量的时候,这种处理方式显示出了先天的不足。因为使用这种方式会创建新的线程,这样势必增加系统的开销。当出现成千上万的线程时,系统的开销已经相当大了,因为要频繁的在上下文之间切换。所以在socket编程里,这种方式,处理线程数不是很大的情况下是比较有优势的。

2.IO completion port 
在winsock2中引入了异步IO的API:IOCP。其实这里也是overlapped的理念。但有不同,如下描述:
这种异步IO的工作方式是:先开一些线程,处在hold的状态下,应用线程和completion port关联起来,当某个线程要处理数据时,就与completion port进行通信,这样就可以进行socket操作了,这种处理方式就是在刚开始的时候,消耗一些资源开线程,处理大数据量的socket通信,如图:

这样一来completion port就可以处理threads和IO Device之间的交互了。
打个比方来说:有很多人早上都去坐地铁,但是,如果不限制人往站台走的速度,售票口就要增加很多个才能处理乘客的请求,这样成本就会增加很多,并且站台上最后会挤满了人,最后导致危机出现;而现在,在进入地铁的时候,加上有序的限流措施,这样一来售票口不用增加,也可以处理乘客的请求,站台上就不会有那么大的压力。在我的理解中,completion port就有着这么一个功能。在处理大数据量的时候,它起着维持秩序的作用。

以上为socket在处理数据量较大时的两种方式。
而在性能测试中,如果开的线程过多,可能某些资源不足导致不停的上下文切换,就会有thread得不到资源,从而出现pending。
如果我们关闭了overlapped,就会同步执行。这时如果CPU速度够快(同时其他资源是足够用的),是可以处理所有请求,并且不会出现pending的。但是,如果thread开的越来越多,也可能导致CPU处理不了,从而出现CPU频繁的上下文切换,或者队列增长。最后出错。这时,我们可以针对性的来提出解决方案了。

转载于:https://www.cnblogs.com/yanghj010/p/3624229.html

IOCP(Input/Output Completion Ports)是一种Windows系统下的高性能网络编程方式,通过异步I/O模型和多线程技术来提升服务器的吞吐量和性能。下面是一个简单的IOCP服务器代码示例: ```c++ #include <iostream> #include <Winsock2.h> #include <Windows.h> #pragma comment(lib, "ws2_32.lib") #define MAX_BUFFER_SIZE 4096 #define SERVER_PORT 8080 struct ClientContext { OVERLAPPED overlapped; SOCKET socket; CHAR buffer[MAX_BUFFER_SIZE]; WSABUF wsaBuf; }; DWORD WINAPI ServerWorkerThread(LPVOID lpParam) { HANDLE iocp = (HANDLE)lpParam; DWORD numBytes = 0; ULONG_PTR completionKey = 0; LPOVERLAPPED overlapped = NULL; ClientContext* clientContext = NULL; while (TRUE) { if (!GetQueuedCompletionStatus(iocp, &numBytes, &completionKey, &overlapped, INFINITE)) { std::cout << "IOCP Error: " << GetLastError() << std::endl; continue; } clientContext = CONTAINING_RECORD(overlapped, ClientContext, overlapped); if (numBytes == 0) { closesocket(clientContext->socket); delete clientContext; continue; } std::cout << "Received data: " << clientContext->buffer << std::endl; // Process client request // Send response to client // Prepare for next I/O operation ZeroMemory(&(clientContext->overlapped), sizeof(OVERLAPPED)); clientContext->wsaBuf.buf = clientContext->buffer; clientContext->wsaBuf.len = MAX_BUFFER_SIZE; DWORD flags = 0; DWORD recvBytes = 0; int ret = WSARecv(clientContext->socket, &(clientContext->wsaBuf), 1, &recvBytes, &flags, &(clientContext->overlapped), NULL); if (ret == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) { std::cout << "WSARecv Error: " << WSAGetLastError() << std::endl; closesocket(clientContext->socket); delete clientContext; } } return 0; } int main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cout << "Failed to initialize Winsock" << std::endl; return -1; } // Create socket SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, 0); if (listenSocket == INVALID_SOCKET) { std::cout << "Failed to create socket" << std::endl; return -1; } // Bind socket SOCKADDR_IN serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(SERVER_PORT); serverAddr.sin_addr.S_un.S_addr = INADDR_ANY; if (bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { std::cout << "Failed to bind socket" << std::endl; return -1; } // Listen if (listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) { std::cout << "Failed to listen" << std::endl; return -1; } // Create IOCP HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (iocp == NULL) { std::cout << "Failed to create IOCP" << std::endl; return -1; } SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); int numThreads = systemInfo.dwNumberOfProcessors * 2; for (int i = 0; i < numThreads; i++) { HANDLE threadHandle = CreateThread(NULL, 0, ServerWorkerThread, iocp, 0, NULL); CloseHandle(threadHandle); } // Associate listen socket with IOCP CreateIoCompletionPort((HANDLE)listenSocket, iocp, 0, 0); while (TRUE) { // Accept incoming client connections SOCKADDR_IN clientAddr; int addrLen = sizeof(clientAddr); SOCKET clientSocket = accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen); if (clientSocket == INVALID_SOCKET) { std::cout << "Failed to accept client connection" << std::endl; continue; } // Register client socket with IOCP ClientContext* clientContext = new ClientContext(); clientContext->socket = clientSocket; ZeroMemory(&(clientContext->overlapped), sizeof(OVERLAPPED)); clientContext->wsaBuf.buf = clientContext->buffer; clientContext->wsaBuf.len = MAX_BUFFER_SIZE; DWORD flags = 0; DWORD recvBytes = 0; int ret = WSARecv(clientSocket, &(clientContext->wsaBuf), 1, &recvBytes, &flags, &(clientContext->overlapped), NULL); if (ret == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) { std::cout << "WSARecv Error: " << WSAGetLastError() << std::endl; closesocket(clientSocket); delete clientContext; continue; } } closesocket(listenSocket); WSACleanup(); return 0; } ``` 以上是一个简单的IOCP服务器代码示例,通过IOCP模型和多线程技术实现异步高性能的网络通信。服务器在循环中等待客户端连接请求,并通过AcceptEx函数接受客户端连接,并将相关的客户端Socket与IOCP关联。每个线程通过WaitForMultipleObjects函数等待来自客户端的I/O完成事件,并进行相应的处理。对于已连接的客户端,通过WSARecv函数接收客户端发送的数据,并根据具体业务逻辑进行处理,然后通过WSASend函数发送响应给客户端,最后继续等待下一个I/O操作的完成。这样的方式可以充分利用系统资源,提高服务器的并发性能和吞吐量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值