我用的是d5 TClientSocket和TServerSocket的非阻塞方式,接收用OnRead和OnClientRead事件处理,在事件中先调用Socket.ReceiveBuf接收到的包头,读取包长度,再调用Socket.ReceiveBuf接收数据,
我的问题是,在发送和接收文件时,会不定时的出现异常,这异常会把程序搞死,我不知道这样做是否安全,如不安全有什么办法解决,大家有没有出现过这样的问题,请高手指教...
我的问题是,在发送和接收文件时,会不定时的出现异常,这异常会把程序搞死,我不知道这样做是否安全,如不安全有什么办法解决,大家有没有出现过这样的问题,请高手指教...
解决方案 »
- ado调用excel表,运行时发生"灾难性故障" 如何办?
- 急!!!一个SQL查询语句的问题!! (在线等)
- Delphi如何访问XML
- 面向对象思想在数据库编程方面的疑惑!请大家指点迷津!参与就有分(分不够再加)!
- @@@@请问:'xxx'变量没有初始化是什么意思呀?@@@@
- Delphi高手成长之路
- TIniFile类疑点提问, 请教
- 如何用一个状态条来显示ADOQUERY读取数据的状态?
- 请解救!!!!为什么用阅览器(pdf)看到《delphi5开发人员指南》的内容,
- 谁可以帮我找到WIN98中的DCOMCNFG.EXE?我的WIN98已经设置成用户级了!
- 请朋友们指教:CPU序列号加密或者硬盘加密方法
- 有关move函数问题
先说阻塞方式, send&recv 异常说明了几种可能, 网络断了, 系统缓冲资源不够, 不管是哪种都应直接关socket非阻塞方式的话 SendBuf 会立即返回, 接下来的事由系统去干了, 不过这时如果在 SendBuf 没完成前又调用 SendBuf 就会异常, 对应的可能性就多点, 也不好说应不应关闭 socket, 但在 send & recv 前判断一下 socket 状态的话就可以像阻塞一样的处理了, 至少, 我是这么作的不记得 ServerSocket&ClientSocket 有类下面这样函数, 贴出来参考,
function Select(ReadReady, WriteReady, ExceptFlag: PBoolean; TimeOut: Integer = -1): Boolean;send 比方
var
WriteReady: Boolean;
begin
Select(nil, WriteReady, nil, 100); // 看看是否写是空闲的, 这个也可以作阻塞用, 最后一个 timeout 就是阻塞时间
if not WriteReady then
// socket is busying
else send...
end;select 函数体, 其中用到的 FHandle 是 socket.Handle
function Select(ReadReady, WriteReady, ExceptFlag: PBoolean; TimeOut: Integer = -1): Boolean;
var
ReadFds: TFDset;
ReadFdsptr: PFDset;
WriteFds: TFDset;
WriteFdsptr: PFDset;
ExceptFds: TFDset;
ExceptFdsptr: PFDset;
tv: timeval;
Timeptr: PTimeval;
begin
if FHandle = INVALID_SOCKET then
begin
result := false;
Exit;
end; if Assigned(ReadReady) then
begin
ReadFdsptr := @ReadFds;
FD_ZERO(ReadFds);
FD_SET(FHandle, ReadFds);
end
else ReadFdsptr := nil; if Assigned(WriteReady) then
begin
WriteFdsptr := @WriteFds;
FD_ZERO(WriteFds);
FD_SET(FHandle, WriteFds);
end
else WriteFdsptr := nil; if Assigned(ExceptFlag) then
begin
ExceptFdsptr := @ExceptFds;
FD_ZERO(ExceptFds);
FD_SET(FHandle, ExceptFds);
end
else ExceptFdsptr := nil; if TimeOut >= 0 then
begin
tv.tv_sec := TimeOut div 1000;
tv.tv_usec := 1000 * (TimeOut mod 1000);
Timeptr := @tv;
end
else Timeptr := nil; try
{$IFDEF MSWINDOWS}
result := CheckError(WinSock.select(FHandle, ReadFdsptr,
WriteFdsptr, ExceptFdsptr, Timeptr), 'select') > 0;
{$ENDIF}
{$IFDEF LINUX}
result := CheckError(Libc.select(FHandle, ReadFdsptr, WriteFdsptr,
ExceptFdsptr, Timeptr), 'select') > 0;
{$ENDIF}
except
result := false;
end; if Assigned(ReadReady) then
ReadReady^ := FD_ISSET(FHandle, ReadFds);
if Assigned(WriteReady) then
WriteReady^ := FD_ISSET(FHandle, WriteFds);
if Assigned(ExceptFlag) then
ExceptFlag^ := FD_ISSET(FHandle, ExceptFds);
end;
ftp://61.152.210.98:20/ThreadBlocking.rar
所以在7.0版本以后,其默认是没有的,需手动添加其包,同时该组件只适用于windows,并不支持其他操作系统,所以,建议用indy的Socket组件。如果你掌握了indy的socket,那么你将对通讯原理开发将会了解的更加透彻。
楼主使用非阻塞方式传输是可以的.
问题全出在具体编码细节上,估计至少这几点没有处理好,这也是很多程序员都容易犯的错误:1,非阻塞SOCKET异常处理,
ONERROR事件一定要处理好的.
2,SOCKET数据'流'读写解析
TCLIENTSOCKET/TSERVERSOCKET没提供数据内容同步的封装(INDY提供得有),这需要自己处理好,需自己根据读到的内容拼接分解.
3,非阻塞SOCKET发送与接收
非阻塞SOCKET发送接收与阻塞SOCKET有区别,发送是进本地队列,失败需延时重发.
4,有可能自定义的应用协议不妥