上次文了一个关于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跟我的程序逻辑是不是冲突,请高手看一下。为什么会这样呢?是不是本身我就不应该使用这个函数在这里重置。。
请高手出马啊
代码是这样的。
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跟我的程序逻辑是不是冲突,请高手看一下。为什么会这样呢?是不是本身我就不应该使用这个函数在这里重置。。
请高手出马啊
昨天终于发现了,原来问题不再这里段代码,而在我服务端。服务端可以正常发送心跳消息,客户端也可以正常接收、发送消息。只是服务端接收客户端消息有阻塞。导致socket连接正常,客户端可以正常收发情况下,服务端不能返回消息。就算是我知道了这种情况,释放掉原来连接重新建立的服务端线程还是不能启动。
呵呵。害的搞了几天一直以为客户端同步或是阻塞的问题。
谢谢僵哥。分继续给上。