Socket向完成端口多次发送消息浅见
2009-07-18 10:48
411 查看
1. 同时发送多个WSARecv消息处理,多余的会有什么情况?
使用代码测试,显示结果为全部返回错误997,表示都可以正常发出recv操作,且多个工作线程同时在检测此socket的多个recv消息,运行片刻立即关闭Client端,发现工作线程出现的异常,1个或2个工作线程中的closesocket函数调用失败,错误码为10038,因此要尽力避免对同一个socket向完成端口发送重复的同一信息。在接受数据时并没有出现重复现象(内部有同步),也就是说只有在断开socket时会有很小不出错的可能,跟线程调度有关。
测试代码如下:Server端:
(侦听线程)
......
//成功与Client建立连接
while(1)
{
while(WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) ==SOCKET_ERROR && WSAGetLastError() ==ERROR_IO_PENDING)
{
printf("WSARecv()2 failed with error %d/n", WSAGetLastError());
Sleep(1000);
}
printf("WSARecv() succeed!/n");
Sleep(5000);
}
......
(工作线程)
......
while(TRUE)
{
//完成端口有消息来了
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)//PerIoData的其他数据成员由此函数在收到数据时填充
{
if(GetLastError() ==64)//套接字无效,有人掉线了
{
printf("Invalid socket %d was closed!/n", PerHandleData->Socket);
if(closesocket(PerHandleData->Socket) ==SOCKET_ERROR)
{
printf("closesocket() failed with error %d/n", WSAGetLastError());
return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
printf("PerIoData at %d was freed!/n", PerIoData);
continue;
}
}
printf("GetQueuedCompletionStatus() 返回BytesTransferred ==%d/n", BytesTransferred);//------
printf("PerIoData->DataBuf.buf ==%s/n", PerIoData->DataBuf.buf);
printf("completion routine running---------/n");
}
Client端:
......
//connect成功与Server取得链接
while(1)
{
//获取键盘输入,并保存
cin>>lpPerIoData->Buffer;
lpPerIoData->DataBuf.buf =lpPerIoData->Buffer;
lpPerIoData->DataBuf.len =DATA_BUFSIZE;
//发送数据
if(WSASend(Client, &(lpPerIoData->DataBuf), 1, &(lpPerIoData->BytesSEND),
0, &(lpPerIoData->Overlapped), NULL) ==SOCKET_ERROR)
{
printf("WSASend() failed with error %d/n", WSAGetLastError());
Sleep(1000);
return;
}
else
printf("Send Succeed!/n");
Sleep(5000);
}
Server打印信息见图片。
2.同时发送多个WSASend消息处理
由于是异步操作所以这个消息经常是立即成功返回0的,但是当完成端口内部的服务线程(不是指工作线程)有很多消息要处理的时候应该会返回997错误,因此WSASend消息是有可能被堆积在未完成消息队列里的,如果服务线程同时执行针对同一个socket的send操作"可能"(这里是我猜的)会引起数据的混乱,因此不应重复调用WSASend发送消息。
3.同时发送WSARecv和WSASend消息
这两者不冲突。
使用代码测试,显示结果为全部返回错误997,表示都可以正常发出recv操作,且多个工作线程同时在检测此socket的多个recv消息,运行片刻立即关闭Client端,发现工作线程出现的异常,1个或2个工作线程中的closesocket函数调用失败,错误码为10038,因此要尽力避免对同一个socket向完成端口发送重复的同一信息。在接受数据时并没有出现重复现象(内部有同步),也就是说只有在断开socket时会有很小不出错的可能,跟线程调度有关。
测试代码如下:Server端:
(侦听线程)
......
//成功与Client建立连接
while(1)
{
while(WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,
&(PerIoData->Overlapped), NULL) ==SOCKET_ERROR && WSAGetLastError() ==ERROR_IO_PENDING)
{
printf("WSARecv()2 failed with error %d/n", WSAGetLastError());
Sleep(1000);
}
printf("WSARecv() succeed!/n");
Sleep(5000);
}
......
(工作线程)
......
while(TRUE)
{
//完成端口有消息来了
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
(LPDWORD)&PerHandleData, (LPOVERLAPPED *) &PerIoData, INFINITE) == 0)//PerIoData的其他数据成员由此函数在收到数据时填充
{
if(GetLastError() ==64)//套接字无效,有人掉线了
{
printf("Invalid socket %d was closed!/n", PerHandleData->Socket);
if(closesocket(PerHandleData->Socket) ==SOCKET_ERROR)
{
printf("closesocket() failed with error %d/n", WSAGetLastError());
return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
printf("PerIoData at %d was freed!/n", PerIoData);
continue;
}
}
printf("GetQueuedCompletionStatus() 返回BytesTransferred ==%d/n", BytesTransferred);//------
printf("PerIoData->DataBuf.buf ==%s/n", PerIoData->DataBuf.buf);
printf("completion routine running---------/n");
}
Client端:
......
//connect成功与Server取得链接
while(1)
{
//获取键盘输入,并保存
cin>>lpPerIoData->Buffer;
lpPerIoData->DataBuf.buf =lpPerIoData->Buffer;
lpPerIoData->DataBuf.len =DATA_BUFSIZE;
//发送数据
if(WSASend(Client, &(lpPerIoData->DataBuf), 1, &(lpPerIoData->BytesSEND),
0, &(lpPerIoData->Overlapped), NULL) ==SOCKET_ERROR)
{
printf("WSASend() failed with error %d/n", WSAGetLastError());
Sleep(1000);
return;
}
else
printf("Send Succeed!/n");
Sleep(5000);
}
Server打印信息见图片。
2.同时发送多个WSASend消息处理
由于是异步操作所以这个消息经常是立即成功返回0的,但是当完成端口内部的服务线程(不是指工作线程)有很多消息要处理的时候应该会返回997错误,因此WSASend消息是有可能被堆积在未完成消息队列里的,如果服务线程同时执行针对同一个socket的send操作"可能"(这里是我猜的)会引起数据的混乱,因此不应重复调用WSASend发送消息。
3.同时发送WSARecv和WSASend消息
这两者不冲突。
相关文章推荐
- Socket编程中如何发送结构体,拼接多次接收消息及获取通信双方地址
- Socket编程中如何发送结构体,拼接多次接收消息及获取通信双方地址
- 刷新页面,socketio会请求多次,为什么?发送成功后,有木有办法就让它停下来。
- socket客户端发送消息到服务器端简单示例
- (unix domain socket)使用udp发送>=128K的消息会报ENOBUFS的错误
- 在Netty底层监控消息发送到Socket的时间
- Socket Server 发送消息机制
- Android Socket 轻松建立连接和发送消息
- Socket 服务器设计核心——发送消息的缓存
- php模拟socket 多次发送数据的实现方法
- android用socket向服务器发送和接收消息 【转自网易闯京城的博客】
- ServerSocket和Socket建立通信(客户端发送消息服务器接收输出)
- WorkerMan学习篇:websocket+workerman聊天功能(三):点对点发送消息模拟(亲测可用_准备尝试着做客服接口)
- (unix domain socket)使用udp发送>=128K的消息会报ENOBUFS的错误
- 深入探讨C#中Socket一次性搞定消息发送
- ServerSocket和Socket建立通信(客户端发送消息服务器接收并返回到客户端接收输出)
- socket方式发送Http GET消息
- Socket发送接收消息简单例子
- 哈工大 java实验4 基于socket的消息发送与文件传输
- php模拟socket一次连接,多次发送数据的实现