重叠I/O模型的 发送会影响 接收吗,几时发送?

重叠I/O模型的 发送会影响 接收吗,何时发送???
本帖最后由 VisualEleven 于 2015-03-09 14:28:57 编辑
开发TCP服务程序,采用TCP 重叠I/O模型 。
客户端不断的向服务器端发送数据,如果检测到某一个数据需要回复,则程序会自动发送给客户端确认命令。
采用三个线程, 第一个线程是接收客户端连接,并保存为全局变量,第二个线程为接收数据线程。
第三个为给客户端发送线程,目前发送要不用send 则会丢失数据,用WSASend则会导致影响WSARecv。
请看看大概是什么原因???




//接收TCP连接
DWORD WINAPI ProcAccept(LPVOID lpParameter)
{
WSADATA     wsaData;
SOCKET      sListen, sClient;
SOCKADDR_IN local, client;
DWORD       dwThreadId;
int         iaddrSize = sizeof(SOCKADDR_IN);

//// Initialize Windows Socket library
WSAStartup(0x0202, &wsaData);

// Create listening socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//// Bind
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));

// Listen
listen(sListen, 64);//3

// Create worker thread
CreateThread(NULL, 0, WorkerThread, lpParameter, 0, &dwThreadId);

HANDLE hSendCmd   = (HANDLE)::CreateThread(NULL,0,ProcSendCmd,lpParameter,0,NULL);

while (!g_theadNET.exit)
{
// Accept a connection
sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);
g_CliSocketArr[g_iTotalConn] = sClient;
g_mapAddr.SetAt(sClientIP,g_iTotalConn);


//通过两种方式得到
// Allocate a PER_IO_OPERATION_DATA structure
g_pPerIODataArr[g_iTotalConn] = (LPPER_IO_OPERATION_DATA)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(PER_IO_OPERATION_DATA));
g_pPerIODataArr[g_iTotalConn]->Buffer.len = MSGSIZE; //接收缓冲长度
g_pPerIODataArr[g_iTotalConn]->Buffer.buf = g_pPerIODataArr[g_iTotalConn]->szMessage; //接收缓冲区域
//创建接收数据事件,绑定该socket
g_CliEventArr[g_iTotalConn] = g_pPerIODataArr[g_iTotalConn]->overlap.hEvent = WSACreateEvent();

// 异步该socket接收数据,即立刻返回,等待事件信号状态。
WSARecv(
g_CliSocketArr[g_iTotalConn],
&g_pPerIODataArr[g_iTotalConn]->Buffer,
1,
&g_pPerIODataArr[g_iTotalConn]->NumberOfBytesRecvd,
&g_pPerIODataArr[g_iTotalConn]->Flags,
&g_pPerIODataArr[g_iTotalConn]->overlap,
NULL);

g_iTotalConn++; //连接数加1
}

closesocket(sListen);

//////////////////////////
WSACleanup();

return 0;
}


//接收TCP连接数据
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
CMainFrame* pMain=(CMainFrame*)lpParam;
///////////////////////////////////////////
int   ret, index;
DWORD cbTransferred;


while (!g_theadNET.exit)
{
ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE); //等待事件信号,1s超时
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
}

index = ret - WSA_WAIT_EVENT_0; //取信号事件的索引号
WSAResetEvent(g_CliEventArr[index]); //将事件重置

WSAGetOverlappedResult( //返回指定套接口上一个重叠操作的结果。
g_CliSocketArr[index], //调用重叠操作时socket
&g_pPerIODataArr[index]->overlap, //指向调用重叠操作时指定的WSAOVERLAPPED结构
&cbTransferred, //接收实际数据长度
TRUE, //指定函数是否等待挂起的重叠操作结束
&g_pPerIODataArr[g_iTotalConn]->Flags); //该变量存放完成状态的附加标志位

if (cbTransferred == 0) //接收为数据长度为0,表示socket已经被关闭
{
// The connection was closed by client
Cleanup(index);
}
else
{
                      
       BYTE arr[MSGSIZE];
   for(int i=0;i<cbTransferred;i++)
   {
   arr[i]=(BYTE)g_pPerIODataArr[index]->szMessage[i];
   //printf("%02X ",arr[i]);
   }
   
// Launch another asynchronous operation
WSARecv(
g_CliSocketArr[index],
&g_pPerIODataArr[index]->Buffer,
1,
&g_pPerIODataArr[index]->NumberOfBytesRecvd,
&g_pPerIODataArr[index]->Flags,
&g_pPerIODataArr[index]->overlap,
NULL);
}
}

return 0;
}

//服务器端发送客户端线程
 DWORD WINAPI ProcSendCmd(LPVOID lpParameter)
{
    while(true)
     {
           if(有数据)
            {
               int index=查找对应的连接;
               int a=send(g_CliSocketArr[index], (char*)buf,len, 0);
              }
     }
}

//程序在运行时发现,如果用send函数发送,则会丢失数据,查看返回值 也标示发送成功了,但就是没收到。

如果用 WSASend发送,重叠结构用接收时候生成的同一结构,则客户端不发送后,服务器端还有数据,请问是什么原因??

int a=WSASend(g_CliSocketArr[index],&DataBuf,1,&SendBytes,0,&g_pPerIODataArr[index]->overlap,NULL);



------解决思路----------------------
socket是双工的,发送和接受不会影响。
------解决思路----------------------
要不要先参考MSDN中自带的相关例子代码?
------解决思路----------------------
引用:
Quote: 引用:

要不要先参考MSDN中自带的相关例子代码?

请问 发送和接收会有影响吗,采用重叠I、O模型的时候。

我也没具体编译链接调试过。

MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl
先下载安装MSDN98,再参考
MSDN98\SAMPLES\VC98\SDK\NETDS\WINSOCK\DT_DLL\HANDLERS.CPP

------解决思路----------------------
重叠IO要用WSASocket创建,并且最后一个参数需要设置成WSA_FLAG_OVERLAPPED