哪位高手帮小弟我看下 WSARecv 接收到多长的数据 在哪里得到
谁帮我看下 WSARecv 接收到多长的数据 在哪里得到?
谁帮我看下 WSARecv 接收到多长的数据 在哪里得到?
------解决思路----------------------
bRet = GetQueuedCompletionStatus(hIocp, &dwBytesTransfered, (PULONG_PTR)&Key, &lpOverlapped, INFINITE);
中的dwBytesTransfered就是投递成功的长度
不管是读投递还是写投递
谁帮我看下 WSARecv 接收到多长的数据 在哪里得到?
#include <tchar.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <strsafe.h>
#include <Winsock2.h>
#include <string>
using namespace std;
#include "../GRSMsSockFun.h"
#pragma comment( lib, "Ws2_32.lib" )
#define GRS_ALLOC(sz) HeapAlloc(GetProcessHeap(),0,sz)
#define GRS_CALLOC(sz) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sz)
#define GRS_CREALLOC(p,sz) HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,p,sz)
#define GRS_SAFEFREE(p) if(NULL != p){HeapFree(GetProcessHeap(),0,p);p=NULL;}
#define GRS_BEGINTHREAD(Fun,Param) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Fun,Param,0,NULL)
#define SOCK_VERH 2
#define SOCK_VERL 2
#define GRS_SERVER_PORT 80
#define DATA_BUFSIZE 4096
struct MYOVERLAPPED
{
WSAOVERLAPPED m_wsaol;
SOCKET m_skListen; //监听套接字句柄
long m_lNetworkEvents;//投递的操作类型(FD_READ/FD_WRITE等)
SOCKET m_socket; //投递操作的SOCKET句柄
void* m_pBuf; //投递操作时的缓冲
size_t m_szBufLen; //缓冲长度
DWORD m_dwTrasBytes; //为WSASent和WSARecv准备的参数
DWORD m_dwFlags; //为WSARecv准备的
};
//IOCP线程池线程函数
DWORD WINAPI IOCPThread(LPVOID lpParameter);
CGRSMsSockFun g_MsSockFun;
SOCKADDR_IN g_service = {};
SOCKADDR_IN g_LocalIP = {};
void _tmain()
{
GRS_USEPRINTF();
WORD wVer = MAKEWORD(SOCK_VERH, SOCK_VERL);
WSADATA wd;
int err = ::WSAStartup(wVer, &wd);
if (0 != err)
{
GRS_PRINTF(_T("无法初始化Socket2系统环境,错误码为:%d!\n"), WSAGetLastError());
return;
}
if (LOBYTE(wd.wVersion) != SOCK_VERH ||
HIBYTE(wd.wVersion) != SOCK_VERL)
{
GRS_PRINTF(_T("无法初始化%d.%d版本的Socket环境!\n"), SOCK_VERH, SOCK_VERL);
WSACleanup();
return;
}
GRS_PRINTF(_T("Winsock库初始化成功!\n\t当前系统中支持最高的Winsock版本为%d.%d\n\t当前应用加载的版本为%d.%d\n")
, LOBYTE(wd.wHighVersion), HIBYTE(wd.wHighVersion)
, LOBYTE(wd.wVersion), HIBYTE(wd.wVersion));
//==========================================================================================================
int iMaxConnectEx = 1;
int iIndex = 0;
HANDLE hIocp = NULL;
HANDLE* phIocpThread = NULL;
SHORT nVirtKey = 0;
WSABUF DataBuf = {};
BYTE buffer[DATA_BUFSIZE] = {};
//用于绑定本地地址的结构
int result = 0;
MYOVERLAPPED *pOLConnectEx = NULL;
SOCKET ConnectSocket = INVALID_SOCKET;
SOCKET* pskConnectArray = NULL;
MYOVERLAPPED** pMyOLArray = NULL;
SOCKADDR_IN saLocal = {};
int iAddrLen = sizeof(SOCKADDR_IN);
const int on = 1;
SYSTEM_INFO si = {};
GetSystemInfo(&si);
//创建IOCP内核对象,允许最大并发CPU个数个线程
hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, si.dwNumberOfProcessors);
//实际创建2倍CPU个数个线程
phIocpThread = (HANDLE*)GRS_CALLOC(2 * si.dwNumberOfProcessors * sizeof(HANDLE));
for (DWORD i = 0; i < 2 * si.dwNumberOfProcessors; i++)
{
phIocpThread[i] = GRS_BEGINTHREAD(IOCPThread, hIocp);
}
g_MsSockFun.LoadAllFun(INVALID_SOCKET);
g_service.sin_family = AF_INET;
g_service.sin_port = htons(GRS_SERVER_PORT);
g_service.sin_addr.s_addr = inet_addr("114.112.73.194");//inet_addr("192.168.2.106");//服务端地址;
g_LocalIP.sin_family = AF_INET;
g_LocalIP.sin_addr.s_addr = INADDR_ANY;//inet_addr("192.168.2.100");
g_LocalIP.sin_port = htons((short)0); //使用0让系统自动分配
pskConnectArray = (SOCKET*)GRS_CALLOC(iMaxConnectEx * sizeof(SOCKET));
pMyOLArray = (MYOVERLAPPED**)GRS_CALLOC(iMaxConnectEx * sizeof(MYOVERLAPPED*));
//发起AcceptEx调用
// for(int i = 0; i < iMaxConnectEx; i ++)
// {
ConnectSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
//将SOCKET句柄与完成端口对象绑定
CreateIoCompletionPort((HANDLE)ConnectSocket, hIocp, NULL, 0);
//允许地址重用
setsockopt(ConnectSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
result = ::bind(ConnectSocket, (LPSOCKADDR)&g_LocalIP, sizeof(SOCKADDR_IN));
getsockname(ConnectSocket, (SOCKADDR*)&saLocal, &iAddrLen);
GRS_PRINTFA("SOCKET绑定被分配地址为[%s:%u]\n"
, inet_ntoa(saLocal.sin_addr), ntohs(saLocal.sin_port));
pOLConnectEx = (MYOVERLAPPED*)GRS_CALLOC(sizeof(MYOVERLAPPED));
pOLConnectEx->m_skListen = INVALID_SOCKET;
pOLConnectEx->m_socket = ConnectSocket;
pOLConnectEx->m_lNetworkEvents = FD_CONNECT;
pOLConnectEx->m_pBuf = GRS_CALLOC(sizeof(SOCKADDR_IN));
pOLConnectEx->m_szBufLen = sizeof(SOCKADDR_IN);
CopyMemory(pOLConnectEx->m_pBuf, &g_service, sizeof(SOCKADDR_IN));
// for (int i = 0; i < 20; i++)
// {
if (!g_MsSockFun.ConnectEx(ConnectSocket
, (SOCKADDR*)pOLConnectEx->m_pBuf, sizeof(SOCKADDR)
, NULL, 0, &pOLConnectEx->m_dwTrasBytes, (LPOVERLAPPED)pOLConnectEx))
{
int iError = WSAGetLastError();
if (ERROR_IO_PENDING != iError
&& WSAECONNRESET != iError)
{
if (INVALID_SOCKET != ConnectSocket)
{
::closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
GRS_SAFEFREE(pOLConnectEx->m_pBuf);
GRS_SAFEFREE(pOLConnectEx);
GRS_PRINTF(_T("调用ConnectEx失败,错误码:%d\n"), iError);
// continue;
}
}
// Sleep(3000);
// }
pskConnectArray[iIndex] = ConnectSocket;
pMyOLArray[iIndex] = pOLConnectEx;
++iIndex;
// GRS_PRINTF(_T("ConnectEx(%d)...\n"),i);
// }
//主线程进入等待状态
do
{
nVirtKey = GetAsyncKeyState(VK_ESCAPE);
if (nVirtKey & 0x8000)
{//按ESC键退出
break;
}
GRS_PRINTF(_T("主线程进入等待状态......\n"));
} while (WAIT_TIMEOUT == WaitForSingleObject(GetCurrentThread(), 10000));
MYOVERLAPPED CloseOL = {};
//向IOCP线程池发送退出消息 利用标志FD_CLOSE标志
CloseOL.m_socket = INVALID_SOCKET;
CloseOL.m_lNetworkEvents = FD_CLOSE;
for (DWORD i = 0; i < 2 * si.dwNumberOfProcessors; i++)
{
PostQueuedCompletionStatus(hIocp, 0, 0, (LPOVERLAPPED)&CloseOL);
}
WaitForMultipleObjects(2 * si.dwNumberOfProcessors, phIocpThread, TRUE, INFINITE);
for (DWORD i = 0; i < 2 * si.dwNumberOfProcessors; i++)
{
CloseHandle(phIocpThread[i]);
}
GRS_SAFEFREE(phIocpThread);
CloseHandle(hIocp);
//释放SOCKET及MYOVERLAPPED资源
for (int i = 0; i < iIndex; i++)
{
closesocket(pskConnectArray[i]);
GRS_SAFEFREE(pMyOLArray[i]);
}
_tsystem(_T("PAUSE"));
::WSACleanup();
}
//IOCP线程池线程函数
DWORD WINAPI IOCPThread(LPVOID lpParameter)
{
GRS_USEPRINTF();
ULONG_PTR Key = NULL;
OVERLAPPED* lpOverlapped = NULL;
MYOVERLAPPED* pMyOl = NULL;
DWORD dwBytesTransfered = 0;
DWORD dwFlags = 0;
BOOL bRet = TRUE;
HANDLE hIocp = (HANDLE)lpParameter;
BOOL bLoop = TRUE;
ULONG nMsgType = 0x1;
DWORD dwMsgLen = 0;
WCHAR pszSendMsg[] = _T("Hello Internet!");
size_t szLen = 0;
StringCchLength(pszSendMsg, 30, &szLen);
ULONG nMsgTail = 0x7FFF;
WSABUF wba[5] = {};
WSABUF mywba = {};
WSABUF mywbb = {};
WCHAR pszRecvBuf[1024] = {};
wba[0].buf = (CHAR*)&nMsgType;
wba[0].len = sizeof(ULONG);
dwMsgLen = (szLen + 1) * sizeof(WCHAR);
wba[1].buf = (CHAR*)&dwMsgLen;
wba[1].len = sizeof(size_t);
wba[2].buf = (CHAR*)pszSendMsg;
wba[2].len = (szLen + 1) * sizeof(WCHAR);
wba[3].buf = (CHAR*)&nMsgTail;
wba[3].len = sizeof(nMsgTail);
string strS = "GET / HTTP/1.1\r\n"
//"Host: www.qq.com\r\n"
"Host: www.****.net\r\n"
"Connection: keep-alive\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36\r\n"
"Accept-Encoding: gzip, deflate, sdch\r\n"
"Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4\r\n\r\n";
//mywba.buf = (CHAR*)&nMsgType;
mywba.buf = (CHAR*)strS.c_str();
mywba.len = strS.length();
CHAR *recvBuf = (CHAR *)GRS_CALLOC(1024 * 1024);
mywbb.buf = (CHAR*)recvBuf;
mywbb.len = 1024 * 1024;
DWORD dwrecvLen = 0;
string strRevc;
int irecv=0;
while (bLoop)
{
bRet = GetQueuedCompletionStatus(hIocp, &dwBytesTransfered, (PULONG_PTR)&Key, &lpOverlapped, INFINITE);
pMyOl = CONTAINING_RECORD(lpOverlapped, MYOVERLAPPED, m_wsaol);
if (FALSE == bRet)
{
GRS_PRINTF(_T("IOCPThread: GetQueuedCompletionStatus 调用失败,错误码: 0x%08x 内部错误码[0x%08x]\n"),
GetLastError(), lpOverlapped->Internal);
continue;
}
switch (pMyOl->m_lNetworkEvents)
{
case FD_CONNECT:
{
GRS_PRINTF(_T("线程[0x%x]完成操作(ConnectEx),缓冲(0x%08x)长度(%ubytes)\n"),
GetCurrentThreadId(), pMyOl->m_pBuf, pMyOl->m_szBufLen);
int nRet = ::setsockopt(
pMyOl->m_socket,
SOL_SOCKET,
SO_UPDATE_CONNECT_CONTEXT,
NULL,
0
);
GRS_SAFEFREE(pMyOl->m_pBuf);
pMyOl->m_szBufLen = 0;
pMyOl->m_lNetworkEvents = FD_WRITE;
WSASend(pMyOl->m_socket, &mywba, 1, &pMyOl->m_dwTrasBytes, 0, (LPOVERLAPPED)&pMyOl->m_wsaol, NULL);
}
break;
case FD_WRITE:
{
//GRS_PRINTF(_T("线程[0x%x]完成操作(WSASend),缓冲(0x%08x)长度(%ubytes)\n"),
// GetCurrentThreadId(),pMyOl->m_pBuf,pMyOl->m_szBufLen);
nMsgType = 0;
ZeroMemory(pszRecvBuf, 1024 * sizeof(WCHAR));
wba[2].buf = (CHAR*)pszRecvBuf;
wba[2].len = 1024 * sizeof(WCHAR);
nMsgTail = 0;
mywba.buf = (CHAR*)pszRecvBuf;
mywba.len = 1024 * sizeof(WCHAR);
pMyOl->m_lNetworkEvents = FD_READ;
strRevc.clear();
mywba.buf = recvBuf;
mywba.len = 1024 * 1024;
//ZeroMemory(recvBuf, 1024 * 1024);
irecv =WSARecv(pMyOl->m_socket, &mywbb, 1, &dwMsgLen/*&pMyOl->m_dwTrasBytes*/, &pMyOl->m_dwFlags, (LPOVERLAPPED)&pMyOl->m_wsaol, NULL);
}
break;
case FD_READ:
{
GRS_PRINTF(_T("线程[0x%x]完成操作(WSARecv),缓冲(0x%08x)长度(%ubytes)\n"),
GetCurrentThreadId(), pMyOl->m_pBuf, dwMsgLen);
printf_s("mywbb.buf len \r\n%d\r\n", strlen(mywbb.buf));
printf_s("mywbb.len len \r\n%d\r\n", mywbb.len);
printf_s("llllllllll \r\n %d\r\n", strRevc.length());
printf_s("irecv \r\n %d\r\n",irecv);
shutdown(pMyOl->m_socket, SD_BOTH);
pMyOl->m_lNetworkEvents = FD_CLOSE;
//回收SOCKET
g_MsSockFun.DisconnectEx(pMyOl->m_socket, (LPOVERLAPPED)pMyOl, TF_REUSE_SOCKET, 0);
}
break;
case FD_CLOSE:
{
if (INVALID_SOCKET == pMyOl->m_socket)
{
bLoop = FALSE;//退出循环
}
else
{
GRS_PRINTF(_T("回收SOCKET成功......\n"));
}
}
break;
default:
{
bLoop = FALSE;
}
break;
}
}
return 0;
}
------解决思路----------------------
bRet = GetQueuedCompletionStatus(hIocp, &dwBytesTransfered, (PULONG_PTR)&Key, &lpOverlapped, INFINITE);
中的dwBytesTransfered就是投递成功的长度
不管是读投递还是写投递