重叠I/O模型的 发送会影响 接收吗,何时发送???
开发TCP服务程序,采用TCP 重叠I/O模型 。
客户端不断的向服务器端发送数据,如果检测到某一个数据需要回复,则程序会自动发送给客户端确认命令。
采用三个线程, 第一个线程是接收客户端连接,并保存为全局变量,第二个线程为接收数据线程。
第三个为给客户端发送线程,目前发送要不用send 则会丢失数据,用WSASend则会导致影响WSARecv。
请看看大概是什么原因???
客户端不断的向服务器端发送数据,如果检测到某一个数据需要回复,则程序会自动发送给客户端确认命令。
采用三个线程, 第一个线程是接收客户端连接,并保存为全局变量,第二个线程为接收数据线程。
第三个为给客户端发送线程,目前发送要不用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);
...全文
相关推荐
Intel Virtualization Technology for Direct I/O
VT-d技术允许中断直接从I/O设备发送到相应的虚拟机,提高了处理效率。5.
c++异步重叠完成例程io封装
- **内存缓存**:预分配缓冲区,减少动态内存分配的影响。总结,C++中的异步重叠I/O封装需要关注接口设计、状态管理、错误处理、线程安全以及用户定制的解包策略。
Socket模型详解
**重叠I/O模型 (Overlapped I/O Model)** - **原理**: 通过使用`OVERLAPPED`结构来异步执行I/O操作。应用程序可以启动I/O操作并在完成后接收通知。
Socket模型c++版本详解
重叠I/O(Overlapped I/O)模型:这是Windows特有的高效I/O模型,允许I/O操作在后台执行,而程序可以继续执行其他任务。
轻量级压缩树,可减少对有效键值存储的I / O放大
SMR驱动器通过重叠写入数据到相邻的磁道来增加存储密度,但这种设计导致了在进行读写操作时需要更频繁地移动磁头,进而增加了I/O放大。


