请教关于函数WSAResetEvent的问题。

piaoxueskysz 2008-01-22 02:14:10
上次文了一个关于TClientWinSocket的问题。非常感谢"僵哥"的回答。经过几天的反反复复的修改测试。终于有点眉目了。
代码是这样的。
FSocket := TClientWinSocket.Create(Integer(not(0)));
//采用阻塞模式
FSocket.ClientType := ctBlocking;


try
FSocket.Open(FHost, FHost, '', 8309); //连接服务端
Timeout := 2000; //2秒超时
HadSendConn := false;
setsockopt(FSocket.SocketHandle, SOL_SOCKET, SO_RCVTIMEO, @Timeout, SizeOf(Timeout));
except
end;
PeekMessage(msg, 0, 0, 0, PM_NOREMOVE);
Event := WSACreateEvent; //创建事件句柄
try
WSAEventSelect(FSocket.SocketHandle, Event, FD_READ or FD_CLOSE);
while (not Terminated) and (FSocket.Connected=True) do
case MsgWaitForMultipleObjects(1, Event, False, 500, QS_ALLINPUT) of
//接收网络消息部分
WAIT_OBJECT_0:
begin
if IsClose(FSocket.SocketHandle, Event) then
begin
{ 'server close' ; }
Break;
end;
//***********接收数据部分*********************
RetLen := FSocket.ReceiveBuf(D.Content, D.Len);
//**********如果接收到非法消息,程序continue
wsaRecMsg := D.Content;
PostMessage(frm_wyClientMain.Handle,WM_GETMES,WParam(wsaRecMsg),Length(wsaRecMsg));
//***********接收数据结束*********
//************重置事件句柄*********
//关键是这句。如果接收到合法消息程序会到这里,事件对象状态清除为未置信号
//也就是这样一句,可能使我的socket连接存在,但是永远不会进入到读状态。
WSAResetEvent(Event);
//********************************
end;
WAIT_OBJECT_0 + 1:
begin
//发送网络消息部分
if PeekMessage(msg, 0, 0, 0, PM_REMOVE) then
begin
case msg.message of
WM_USER:
begin
//发送自定义消息 如 登陆,注销等
end;
WM_CLOSE:
begin
//发送客户端正常关闭消息
//正常退出,服务端会对数据库做相应操作
//退出线程
break;
end;
end;
end;
end;
WAIT_TIMEOUT:
begin
//线程启动时发送连接消息
if HadSendConn = false then
begin
//置已连接标志为真
HadSendConn := true;
end;
end;
end;
finally
WSACloseEvent(Event);
end;




上次僵哥说要我全部用API函数,他说可能TClientWinSocket会与我的代码有冲突。但是改了后还是一样。现在的问题是这个函数WSAResetEvent跟我的程序逻辑是不是冲突,请高手看一下。为什么会这样呢?是不是本身我就不应该使用这个函数在这里重置。。
请高手出马啊。。。。。。。。。
...全文
96 点赞 收藏 3
写回复
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
piaoxueskysz 2008-01-23
谢谢。。。。
昨天终于发现了,原来问题不再这里段代码,而在我服务端。服务端可以正常发送心跳消息,客户端也可以正常接收、发送消息。只是服务端接收客户端消息有阻塞。导致socket连接正常,客户端可以正常收发情况下,服务端不能返回消息。就算是我知道了这种情况,释放掉原来连接重新建立的服务端线程还是不能启动。
呵呵。害的搞了几天一直以为客户端同步或是阻塞的问题。
谢谢僵哥。分继续给上。
回复
僵哥 2008-01-22
MSDN当中有这样一段描述,Issuing a WSAEventSelect for a socket cancels any previous WSAAsyncSelect or WSAEventSelect for the same socket and clears the internal network event record.意思也就是WSAEventSelect是可以覆盖掉原来的WSAAsyncSelect,但是如果服务器是一个主动服务(比如SMTP服务等有欢迎消息发送的,或者是完全主动推送的,那么在被覆盖掉之前会是什么情况?

另外PeekMessage当中,除了上面的几个消息,以后的消息怎么办?就算是独立的线程,那如果里面还有别的如TTimer,那么这个WM_TIMER消息不就丢弃了?

另外还是之前提到过的那个同步的问题。PostMessage不等待消息的处理。wsaRecMsg会是怎么样的一种情况?
回复
僵哥 2008-01-22
TClientWinSocket继续于TCustomWinSocket,其Open方法在TCustomWinSocket当中有实现。当采用block模式,在Open调用过程当中就会调用TCustomWinSocket.DoOpen,而DoOpen又会调用TCustomWinSocket.DoSetAsyncStyles,在DoSetAsyncStyles当中则有一个WSAAsyncSelect,而这之后,楼主再调用WSAEventSelect,你觉得系统会听谁的?
回复
发动态
发帖子
网络通信/分布式开发
创建于2007-08-02

1565

社区成员

Delphi 网络通信/分布式开发
申请成为版主
社区公告
暂无公告