您的位置:首页 > 其它

调用WSAAsyncSelect后,什么时候触发FD_WRITE消息啊

2008-10-17 19:59 316 查看
开发服务器端程序时,调用WSAAsyncSelect将套接字设置为异步非阻塞,服务器端和客户端的通讯是客户端先向服务器端发送一组数据,服务器给客户端回复一组数据,就这样反复执行。

//消息响应函数
...
case FD_READ: //网络数据包到达事件
{
OnReceive(CurSock);
break;
}
case FD_WRITE: //发送网络数据事件
{
OnSend(CurSock);
break;
}
...

我的设想是调用OnReceive接收数据后后马上传递给OnSend函数进行处理,处理完后OnSend函数将处理后的数据发送给客户端。可是我怎么控制OnReceive和OnSend的执行顺序啊?
FD_READ事件是当对方发送数据过来后就应该自动触发的,FD_WRITE是怎么触发的?按我的情况,最好响应FD_READ事件后响应FD_WRITE事件。请高手给指点迷津。

还有个小问题,使用WSAAsyncSelect将socket设置为异步非阻塞模式后,还能用send吗?还是必须用WSASend? 100 回复次数:10
第1个回答
FD_WRITE事件是socket已经准备好了,你可以调用send了,这个时候触发的,如果未收到这个消息就调用send会失败。

你可以定义两个信号量,假设为HasData和ReadyToSend,OnReceive中检查如果ReadyToSend被设置则调用OnSend并清除该信号,否则设置HasData信号;FD_WRITE中检查如果HasData被设置则调用OnSend并清除该信号,否则设置ReadyToSend信号。因为这些操作都是单线程,所以使用信号量即可,不必使用同步对象。

第2个回答
补充一下FD_WRITE只会触发一次

第3个回答
FD_WRITE只会触发一次?我试试。

第4个回答
FD_WRITE事件是socket已经准备好了,你可以调用send了,这个时候触发的,如果未收到这个消息就调用send会失败。
///

那也就是说当我接收到数据后,直接调用send是不行的了?

case FD_READ: //网络数据包到达事件
{
OnReceive(CurSock);
send(); //直接发送数据

break;
}

给我的感觉是基于消息的异步模式下,FD_READ和FD_WRITE事件都是被动触发的,就是只有FD_READ和FD_WRITE事件被触发了,才可以发送和接收数据。那如果我在对话框中加一个按钮,希望点击按钮后,就能发送出去一条数据,该怎么做?又或者我希望服务器端周期性的发送数据给客户端,又该怎么实现?

第5个回答
FD_WRITE感觉用处不太大,你要发送数据的时候,直接SEND就可以了

第6个回答
FD_WRITE感觉用处不太大,你要发送数据的时候,直接SEND就可以了
///
FD_WRITE事件是socket已经准备好了,你可以调用send了,这个时候触发的,如果未收到这个消息就调用send会失败。
////

以上两种说法究竟哪种是正确的?

第7个回答
都是正确的因为,FD_WRITE只会触发一次

假如你connect之前使用,WSAAsyncSelect
那么你就会先收到FD_CONNECT,紧接着,是FD_WRITE
以后就再也不会收到FD_WRITE,所以说 连接成功之后就可以随便发数据了.

在你未收到FD_WRITE的时候 调用Send肯定会失败.

第8个回答
我在1楼提的做法有误,FD_WRITE是在连接建立或者发送数据失败返回WSAEWOULDBLOCK之后,socket准备就绪后触发的。所以一般情况下你可以直接send,如果send失败且返回WSAEWOULDBLOCK时可以再次等待FD_WRITE事件。

你可以在OnReceive接收数据后立即send,如果send失败且错误码是WSAEWOULDBLOCK时,把要发送的数据挂起,并做一个标记,在响应FD_WRITE事件时判断这个标记发送数据。

第9个回答
FD_WRITE在两种情况下被触发
1.如果socket跟远程目标连接上后(connect()或connectEx()等),就会触发到FD_WRITE(如果socket在调用connect()等API前就将FD_WRITE用WSAAsyncSelect()设置了的话)
2.当socket有数据要发送,而且系统缓冲有空闲位置让你发数据(一般情况下是发送数据,但WSAGetLastError()返回WSAEWOULDBLOCK错误,说明系统缓冲已满,当系统缓冲有位置可发送数据后,就会触发FD_WRITE)

第10个回答
"都是正确的因为,FD_WRITE只会触发一次

假如你connect之前使用,WSAAsyncSelect
那么你就会先收到FD_CONNECT,紧接着,是FD_WRITE
以后就再也不会收到FD_WRITE,所以说 连接成功之后就可以随便发数据了.

在你未收到FD_WRITE的时候 调用Send肯定会失败."

上面说法是有问题的.FD_WRITE不会只触发一次,可以是很多次.只要用send(),WSASend()等发数据,WSAGetLastError()返回WSAEWOULDBLOCK错误,那么等到系统缓冲可再发送数据时,就会有FD_WRITE被触发.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: