VisualEleven你好,请教重叠 io问题(代码是出自你博客上的)

liulin2018 2012-08-25 10:25:15
typedef enum _OPERATION_INFO
{
OP_NULL,
OP_READ,
OP_WRITE
}OPERATIONINFO

以上这个结构体 是你定义的, 我用 vs2008搜了一下关于这个结构体的引用。


Searching for 'nOpType'...
E:\c++\fff\ovlapaped.cpp(44): nOpType = OP_NULL;
E:\c++\fff\ovlapaped.cpp(52): OPERATIONINFO nOpType;
E:\c++\fff\ovlapaped.cpp(143): g_ol[g_nIndex]->nOpType = OP_READ;
E:\c++\fff\ovlapaped.cpp(193): switch(g_ol[dwIndex]->nOpType)
E:\c++\fff\ovlapaped.cpp(198): g_ol[dwIndex]->nOpType = OP_WRITE;
E:\c++\fff\ovlapaped.cpp(213): g_ol[dwIndex]->nOpType = OP_READ;
The file 'E:\c++\fff\Debug\fff_manifest.rc' is unicode and cannot be read.
6 occurrence(s) have been found.


发现: g_ol[g_nIndex]->nOpType 这个东西,谁来对其赋值呢?(或者说,谁来修改它的值呢?)

几乎没有。 为什么可以根据它,用switch 进行 判断是否是 可读,可写呢?

期盼你的回复,谢谢了.





// NetWork.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <Winsock2.h>
#include <Windows.h>
#include <process.h>
#pragma comment(lib, "WS2_32.lib")

#define MAX_BUFFER 256
#define MAX_TIMEOUT 1000

typedef enum _OPERATION_INFO
{
OP_NULL,
OP_READ,
OP_WRITE
}OPERATIONINFO;

typedef struct _OVERLAPPED_INFO_
{
public:
_OVERLAPPED_INFO_()
{
Clean();
}
~_OVERLAPPED_INFO_()
{
Clean();
}
protected:
void Clean()
{
ol.hEvent = NULL;
sock = INVALID_SOCKET;
memset(&addr, 0, sizeof(addr));
addr.sin_addr.S_un.S_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
wsaBuf.buf = szBuf;
wsaBuf.len = MAX_BUFFER;
memset(szBuf, 0, sizeof(szBuf));
nOpType = OP_NULL;
}
public:
WSAOVERLAPPED ol;
SOCKET sock;
SOCKADDR_IN addr;
WSABUF wsaBuf;
char szBuf[MAX_BUFFER];
OPERATIONINFO nOpType;
}OVERLAPPEDINFO, *POVERLAPPEDINFO;

WSAEVENT g_event[WSA_MAXIMUM_WAIT_EVENTS] = {0};
OVERLAPPEDINFO* g_ol[WSA_MAXIMUM_WAIT_EVENTS] = {0};
int g_nIndex = 0;
BOOL g_bExitThread = FALSE;

unsigned __stdcall ThreadProc(LPVOID lParam);

int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
if(0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
{
printf("WSAStartup failed with error code: %d/n", GetLastError());
return EXIT_FAILURE;
}
if(2 != HIBYTE(wsaData.wVersion) || 2 != LOBYTE(wsaData.wVersion))
{
printf("Socket version not supported./n");
WSACleanup();
return EXIT_FAILURE;
}
SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(INVALID_SOCKET == sListen)
{
printf("socket failed with error code: %d/n", WSAGetLastError());
WSACleanup();
return EXIT_FAILURE;
}
SOCKADDR_IN addr = {0};
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(5050);
if(SOCKET_ERROR == bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)))
{
printf("bind failed with error code: %d/n", WSAGetLastError());
closesocket(sListen);
sListen = INVALID_SOCKET;
WSACleanup();
return EXIT_FAILURE;
}
if(SOCKET_ERROR == listen(sListen, 5))
{
printf("listen failed with error code: %d/n", WSAGetLastError());
closesocket(sListen);
sListen = INVALID_SOCKET;
WSACleanup();
return EXIT_FAILURE;
}
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, NULL);
if(NULL == hThread)
{
printf("_beginthreadex failed with error code: %d/n", GetLastError());
closesocket(sListen);
sListen = INVALID_SOCKET;
WSACleanup();
return EXIT_FAILURE;
}

printf("Server start listen and wait for client to connect .../n");

SOCKADDR_IN remote = {0};
int len = sizeof(remote);

while(TRUE)
{
if(g_nIndex >= WSA_MAXIMUM_WAIT_EVENTS)
{
printf("Too many connect, wait for disconnect .../n");
continue;
}
SOCKET sNew = accept(sListen, (LPSOCKADDR)&remote, &len);
if(INVALID_SOCKET == sNew)
{
printf("accept failed with error code: %d/n", WSAGetLastError());
continue;
}
printf("<IP: %s, Port: %d> client come in./n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
DWORD dwTrans = 0;
DWORD dwFlags = 0;
g_ol[g_nIndex] = new OVERLAPPEDINFO;
g_ol[g_nIndex]->sock = sNew;
memcpy(&g_ol[g_nIndex]->addr, &remote, sizeof(remote));
g_event[g_nIndex] = g_ol[g_nIndex]->ol.hEvent = WSACreateEvent();
g_ol[g_nIndex]->nOpType = OP_READ;
if(SOCKET_ERROR == WSARecv(g_ol[g_nIndex]->sock, &(g_ol[g_nIndex]->wsaBuf), 1, &dwTrans, &dwFlags, (LPWSAOVERLAPPED)&(g_ol[g_nIndex]->ol), NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSARecv failed with error code: %d/n", WSAGetLastError());
closesocket(g_ol[g_nIndex]->sock);
delete g_ol[g_nIndex];
g_ol[g_nIndex] = NULL;
continue;
}
}
g_nIndex++;
}
// End of thread and exit process
g_bExitThread = TRUE; // Exit thread.
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);

WSACleanup();
return 0;
}

unsigned __stdcall ThreadProc(LPVOID lParam)
{
while(!g_bExitThread)
{
DWORD dwTrans = 0;
DWORD dwFlags = 0;
DWORD dwIndex = WSAWaitForMultipleEvents(g_nIndex, g_event, FALSE, MAX_TIMEOUT, FALSE);
if(WSA_WAIT_FAILED == dwIndex || WSA_WAIT_TIMEOUT == dwIndex)
{
continue;
}

dwIndex -= WSA_WAIT_EVENT_0;
for(int i = dwIndex; i < g_nIndex; i++)
{
dwIndex = WSAWaitForMultipleEvents(1, &g_event[dwIndex], TRUE, INFINITE, FALSE);
if(WSA_WAIT_FAILED == dwIndex)
{
continue;
}
dwIndex -= WSA_WAIT_EVENT_0;
WSAResetEvent(g_event[dwIndex]);
BOOL bRet = WSAGetOverlappedResult(g_ol[dwIndex]->sock, &(g_ol[dwIndex]->ol), &dwTrans, FALSE, &dwFlags);
if(bRet)
{
if(dwTrans > 0)
{
switch(g_ol[dwIndex]->nOpType)
{
case OP_READ:
{
printf("recv client <%s:%d> data: %s/n", inet_ntoa(g_ol[dwIndex]->addr.sin_addr), ntohs(g_ol[dwIndex]->addr.sin_port), g_ol[dwIndex]->szBuf);
g_ol[dwIndex]->nOpType = OP_WRITE;
memset(&(g_ol[dwIndex]->ol), 0, sizeof(g_ol[dwIndex]->ol));
if(SOCKET_ERROR == WSASend(g_ol[dwIndex]->sock, &(g_ol[dwIndex]->wsaBuf), 1, &dwTrans, dwFlags, &(g_ol[dwIndex]->ol), NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSASend failed with error code: %d/n", WSAGetLastError());
continue;
}
}
}
break;

case OP_WRITE:
{
g_ol[dwIndex]->nOpType = OP_READ;
memset(&(g_ol[dwIndex]->ol), 0, sizeof(g_ol[dwIndex]->ol));
memset(g_ol[dwIndex]->szBuf, 0, sizeof(g_ol[dwIndex]->szBuf));
dwFlags = 0;
g_ol[dwIndex]->wsaBuf.buf = g_ol[dwIndex]->szBuf;
dwTrans = g_ol[dwIndex]->wsaBuf.len = MAX_BUFFER;
if(SOCKET_ERROR == WSARecv(g_ol[dwIndex]->sock, &(g_ol[dwIndex]->wsaBuf), 1, &dwTrans, &dwFlags, &(g_ol[dwIndex]->ol), NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSARecv failed with error code: %d/n", WSAGetLastError());
continue;
}
}
}
break;

default:
break;
}
}
else
{
printf("client <%s : %d> leave./n", inet_ntoa(g_ol[dwIndex]->addr.sin_addr), ntohs(g_ol[dwIndex]->addr.sin_port));
closesocket(g_ol[dwIndex]->sock);
WSACloseEvent(g_event[dwIndex]);
delete g_ol[dwIndex];
// Rebuild array
for(int i= dwIndex; i<g_nIndex-1; i++)
{
g_event[i] = g_event[i+1];
g_ol[i] = g_ol[i+1];
}
g_nIndex--;
}
}
else
{
printf("WSAGetOverlappedResult failed with error: %d/n", WSAGetLastError());
}
}
}
printf("Server to exit ... /n");

return 0;
}







问题2: 惊奇的发现 重叠io和事件选择模型(WSAEventSelect) 有很多相似,也是所谓的事件,某个事件产生,就。。。。。。

...全文
117 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
smwhotjay 2012-08-28
  • 打赏
  • 举报
回复
等事件.设置了max_timeout. 那么超过了时间.事件没等到. 他就函数返回了呗,原因就是超时了.
正常.
liulin2018 2012-08-26
  • 打赏
  • 举报
回复
你好,我已经去掉了 主线程的那段代码。

然后自己写了一个客户端去连接,连接成功。

在子线程中设置断点,发现每次都提示超时。我甚是奇怪,



MAX_TIMEOUT 我改成了4000




客户端的发送数据的代码为:
for(int i=0; i<3000;i++)

{
Sleep(200);

send(s,buf,100,0);
}



服务端子线程每次都continue

DWORD dwIndex = WSAWaitForMultipleEvents(g_nIndex, g_event, FALSE, MAX_TIMEOUT, FALSE);
if(WSA_WAIT_FAILED == dwIndex || WSA_WAIT_TIMEOUT == dwIndex)
{
continue;
}

不断的超时,这是什么原因。 诡异?



Eleven 2012-08-26
  • 打赏
  • 举报
回复
我写的是一个简单的echo服务器,服务器接收到客户端发送的数据以后再返还给客户端,我记得好像是这样的。
工作线程的里OP_WRITE那些代码可以使不要的,你去掉应该也不影响的。
liulin2018 2012-08-25
  • 打赏
  • 举报
回复
方便再解释一个问题嘛, 就一会功夫,劳累你了

g_event[g_nIndex] = g_ol[g_nIndex]->ol.hEvent = WSACreateEvent();
g_ol[g_nIndex]->nOpType = OP_READ;
if(SOCKET_ERROR == WSARecv(g_ol[g_nIndex]->sock, &(g_ol[g_nIndex]->wsaBuf), 1, &dwTrans, &dwFlags, (LPWSAOVERLAPPED)&(g_ol[g_nIndex]->ol), NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSARecv failed with error code: %d/n", WSAGetLastError());
closesocket(g_ol[g_nIndex]->sock);
delete g_ol[g_nIndex];
g_ol[g_nIndex] = NULL;
continue;
}
}
g_nIndex++;

这小段是 来自主线程,


子线程中也是有的

我是这么想的, 主线程中,完成监听,绑定, 然后 接受 客户端的连接即可。 子线程接受数据

为什么 WSARecv 会在主线程、子线程中都出现呢?


这是刻意的,还是随意设计的。

Eleven 2012-08-25
  • 打赏
  • 举报
回复
E:\c++\fff\ovlapaped.cpp(143): g_ol[g_nIndex]->nOpType = OP_READ;
E:\c++\fff\ovlapaped.cpp(198): g_ol[dwIndex]->nOpType = OP_WRITE;
E:\c++\fff\ovlapaped.cpp(213): g_ol[dwIndex]->nOpType = OP_READ;
-----------------------
这里不是有对他们进行赋值吗?你先定义好你的重叠结构,然后投递他们WSASend/WSARecv。然后就等待事件对象signal状态了,然后通过WSAGetOverlappedResult查询结果,是读操作完成还是写操作完成之类的了。

注意不要破坏你的重叠结构,在投递IO的过程中。

16,472

社区成员

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

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

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