开发服务器端程序时,调用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
第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被触发.
在服务器端程序开发中,通过WSAAsyncSelect设置套接字为异步非阻塞模式。FD_READ事件在客户端发送数据后自动触发,用于接收数据。而FD_WRITE事件的触发存在疑惑,讨论中提到FD_WRITE会在socket准备好发送时触发,可能在连接建立或发送失败返回WSAEWOULDBLOCK后。直接使用send可能会失败,需要根据FD_WRITE事件来确定发送时机。对于想要主动发送数据的情况,可以在接收数据后立即尝试send,或者在按钮点击或特定周期时触发发送操作。FD_WRITE的触发并不局限于一次,而是在系统缓冲允许发送时多次触发。
1842

被折叠的 条评论
为什么被折叠?



