WSARecv提供多个缓冲区.

vcsongs 2002-09-29 11:08:27
为了提高性能, 给WSARecv函数提供多于一个的WSABUF, 当函数执行完毕之后, 我怎么才能够知道哪个WSABUF里面才有我需要的数据呢?
谢谢!
...全文
336 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
fishboyzyf 2002-09-29
  • 打赏
  • 举报
回复
WSARecv时作啥的?
请指点!
vcsongs 2002-09-29
  • 打赏
  • 举报
回复
不好意思, 查了资料, 没有发现GetQueuedCompletionStatus的哪个参数有此功能请再指点, 谢谢!
javanew 2002-09-29
  • 打赏
  • 举报
回复
我想去看看
oldworm 2002-09-29
  • 打赏
  • 举报
回复
下面有个完整的例子,希望对你理解WSARecv有所帮助

//
// GetHTTP3.cpp -- Retrieve a file from a HTTP server
//
// This version uses overlapped I/O
// with a completion function.
//
// Compile and link with ws2_32.lib
//

#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <winsock2.h>


void GetHTTP(LPCSTR lpServerName, LPCSTR lpFileName);

//
// Overlapped I/O completion function
//
void CALLBACK RecvComplete(DWORD dwError,
DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped,
DWORD dwFlags);

// Helper macro for displaying errors
#define PRINTERROR(s) \
fprintf(stderr,"\n%s %d\n", s, WSAGetLastError())

#define BUFFER_SIZE 1024

//
// Structure used to pass
// additional info to the
// completion function
//
typedef struct tagIOREQUEST
{
WSAOVERLAPPED over; // Must be first
SOCKET Socket;
BOOL fFinished;
LPBYTE pBuffer;
}IOREQUEST, *LPIOREQUEST;


void main(int argc, char **argv)
{
WORD wVersionRequested = WINSOCK_VERSION;
WSADATA wsaData;
int nRet;

//
// Check arguments
//
if (argc != 3)
{
fprintf(stderr,
"\nSyntax: GetHTTP ServerName FullPathName\n");
return;
}

//
// Initialize WinSock.dll
//
nRet = WSAStartup(wVersionRequested, &wsaData);
if (nRet)
{
fprintf(stderr, "\nWSAStartup() error (%d)\n",
nRet);
WSACleanup();
return;
}

//
// Check WinSock version
//
if (wsaData.wVersion != wVersionRequested)
{
fprintf(stderr,"\nWinSock version not supported\n");
WSACleanup();
return;
}

//
// Set "stdout" to binary mode
// so that redirection will work
// for binary files (.gif, .jpg, .exe, etc.)
//
_setmode(_fileno(stdout), _O_BINARY);

//
// Call GetHTTP() to do all the work
//
GetHTTP(argv[1], argv[2]);

WSACleanup();
}


void GetHTTP(LPCSTR lpServerName, LPCSTR lpFileName)
{
LPHOSTENT lpHostEntry;
SOCKADDR_IN saServer;
SOCKET Socket;
int nRet;

//
// Lookup the host address
//
lpHostEntry = gethostbyname(lpServerName);
if (lpHostEntry == NULL)
{
PRINTERROR("socket()");
return;
}

// Create a TCP/IP stream socket
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Socket == INVALID_SOCKET)
{
PRINTERROR("socket()");
return;
}

//
// Fill in the rest of the server address structure
//
saServer.sin_family = AF_INET;
saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
saServer.sin_port = htons(80);

//
// Connect the socket
//
nRet = connect(Socket, (LPSOCKADDR)&saServer, sizeof(SOCKADDR_IN));
if (nRet == SOCKET_ERROR)
{
PRINTERROR("connect()");
closesocket(Socket);
return;
}

//
// Format the HTTP request
// and send it
//
char szBuffer[1024];
sprintf(szBuffer, "GET %s\n", lpFileName);
nRet = send(Socket, szBuffer, strlen(szBuffer), 0);
if (nRet == SOCKET_ERROR)
{
PRINTERROR("send()");
closesocket(Socket);
return;
}

//
// We're connected, so we can now
// post a receive buffer
//

//
// We use a little trick here to pass additional
// information to out completion function.
// We append any additional info onto the end
// of a WSAOVERLAPPED structure and pass it
// as the lpOverlapped parameter to WSARecv()
// When the completion function is called,
// this additional info is then available.
//
BYTE aBuffer[BUFFER_SIZE];
IOREQUEST ioRequest;
memset(&ioRequest.over, 0, sizeof(WSAOVERLAPPED));
ioRequest.Socket = Socket;
ioRequest.fFinished = FALSE;
ioRequest.pBuffer = aBuffer;

WSABUF wsabuf;
wsabuf.len = BUFFER_SIZE;
wsabuf.buf = (char *)aBuffer;

DWORD dwRecv;
DWORD dwFlags = 0;
nRet = WSARecv(Socket,
&wsabuf,
1,
&dwRecv,
&dwFlags,
(LPWSAOVERLAPPED)&ioRequest,
RecvComplete);
if (nRet == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
PRINTERROR("WSARecv()");
closesocket(Socket);
return;
}
}

// Receive the file contents and print to stdout
while(1)
{
//
// We could do other processing here
//

//
// Use the SleepEx() function to signal
// that we are in an altertable wait state
//
SleepEx(0, TRUE);

//
// If the completion function says we're finished
//
if (ioRequest.fFinished)
break;
}
closesocket(Socket);
}

void CALLBACK RecvComplete(DWORD dwError,
DWORD cbRecv,
LPWSAOVERLAPPED lpOver,
DWORD dwFlags)
{
//
// Check for errors
//
if (dwError)
{
fprintf(stderr,"\nRecvComplete() error: %ld",
dwError);
return;
}

LPIOREQUEST pReq = (LPIOREQUEST)lpOver;

//
// If no error and no data returned,
// then the connection has been closed.
//
if (cbRecv == 0)
{
pReq->fFinished = TRUE;
return;
}

fprintf(stderr,"\nRecvComplete(): %ld bytes received", cbRecv);
//
// Write the received data to stdout
//
fwrite(pReq->pBuffer, cbRecv, 1, stdout);

//
// And then post the buffer to receive again
//
WSABUF wsabuf;
wsabuf.len = BUFFER_SIZE;
wsabuf.buf = (char *)pReq->pBuffer;

DWORD dwRecv;
dwFlags = 0;
int nRet;
nRet = WSARecv(pReq->Socket,
&wsabuf,
1,
&dwRecv,
&dwFlags,
lpOver,
RecvComplete);
if (nRet == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
PRINTERROR("RePost with WSARecv()");
pReq->fFinished = TRUE;
}
}
}

oldworm 2002-09-29
  • 打赏
  • 举报
回复
关于winsock编程,请看下面两个资源:

http://tangentsoft.net/wskfaq/
http://www.sockaddr.com/

上面有一些经典例子,值得一看。


realdreamer 2002-09-29
  • 打赏
  • 举报
回复
WSARecv 函数若执行成功. 数据会从第一个到最后一个 WSABUF 顺序着排列返回.
everandforever 2002-09-29
  • 打赏
  • 举报
回复
是完成端口么?如果是的话你的那个线程里的QUERY。。。函数会返回WSABUF的指针。一般WSARECV就是拿来做完成端口的,一般应用RECV就足够了。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧