那么,再问:
TServerSocket和TClienSocket 的多线程和同步问题:
ServerSocket 用 多线程 吗?
请各位达人尽量详细说明,我在通讯上是菜鸟...哪里有例子??
TServerSocket和TClienSocket 的多线程和同步问题:
ServerSocket 用 多线程 吗?
请各位达人尽量详细说明,我在通讯上是菜鸟...哪里有例子??
解决方案 »
- 如何显示带有自定义标题的对话框
- 使用ListView控件,第一列Item不能居中,为什么???
- 用adoquery进行动态sql编程时,如何传递参数??急用。
- 怎样让Edit中的Text居中显示,默认都是靠左的,请问怎样居中!
- 如何实现关机时自动运行某程序,在线等待!!!!!解决即结贴
- 用程序实现:如何将一个rar文件解压出到当前目录下呢?
- 急需Delphi中API函数和操作功能。
- 请教关于DBGRID的问题!!!在线给分!
- ---我想返回其中的sumqty,怎么做?
- !!!!寻 Windows API 函数
- FastReport 能否传个二维数组参数?
- 在用WEBBROWSER开发浏览器时,CTRL+N的问题
然后在 TServerSocket 的 OnGetThread 中写到
SocketThread := TMyServerThread.Create(Self, ClientSocket);
SocketThread.Resume;从 TServerClientThread 中派生的线程 的最主要方法就是 procedure ClientExecute; override;
private
... //好多东东去掉了
FLastActivity: TDateTime;
function GetLastActivity: TDateTime; function WaitForData(Timeout: Integer): TWaitResult;
protected
procedure ClientExecute; override;
...
public
constructor Create(ACollector: TTCPCollector; ASocket:
TServerClientWinSocket);
destructor Destroy; override; property LastActivity: TDateTime read GetLastActivity;
end;constructor TTCPCollectorThread.Create(ACollector: TTCPCollector; ASocket:
TServerClientWinSocket);
begin
FLastActivity := Now; inherited Create(true, ASocket);
end;destructor TTCPCollectorThread.Destroy;
begin
...
inherited;
end;procedure TTCPCollectorThread.ClientExecute;
begin
CoInitialize(nil); // 初始化 COM, 我的要操作 COM, 没有的去掉
try
while (not Terminated) and ClientSocket.Connected do
begin
try
case WaitForData(3*60*1000{FCollector.Timeout}) of // 3分种 wrSignaled:
begin
FLastActivity := Now();
// 有数据进来, 处理
end; wrTimeout: // 线程空闲超时
break; wrError: // 由客户机关闭了连接
break;
end;
except
on e: Exception do
// log 处理中的异常
end;
end; finally
// 加入清理代码, 在线程中的私有成员, 出了这个函数后, 线程不一定释放(ServerSocket 的 Cache 大小决定), 但 socket 关闭, 所以清除线程的私有成员上次使用的值
CoUninitialize;
end;
end;function TTCPCollectorThread.WaitForData(Timeout: Integer): TWaitResult;
var
FDSet: TFDSet;
TimeVal: TTimeVal;
ReturnCode: Integer;
begin
FD_ZERO(FDSet);
FD_SET(ClientSocket.SocketHandle, FDSet);
TimeVal.tv_sec := Timeout div 1000;
TimeVal.tv_usec := Timeout mod 1000; ReturnCode := select(0, @FDSet, nil, nil, @TimeVal); if ReturnCode > 0 then // client 有数据
begin
if ClientSocket.ReceiveLength <= 0 then result := wrError // 是 client 断线
else result := wrSignaled
end
else if ReturnCode = 0 then
result := wrTimeout // 指定时间内没有数据
else result := wrError; // 理论上不可能发生, 在设了带外数据后, 有带外数据, 也是用这个通知
end;
SocketThread.Resume;组件还是用 ServerSocket, 只不过代替了他的线程部分
begin
FLastActivity := Now();
// 有数据进来, 处理, 这里加几句
end;这里加几句var
str: string;SetLength(str, ClientSocket.ReceiveLength);
ClientSocket.ReceiveBuf(PChar(str)^, ClientSocket.ReceiveLength)
if str = 'hello' then
begin
str := 'world';
ClientSocket.SendBuf(PChar(str)^, Length(str)); // 哈, 当然没那么简单, 不过也就是这样啦
end;
var
Operation: string;
Command: string;
begin
CoInitialize(nil);
try
FLastActivity := Now; while not Terminated and ClientSocket.Connected do
begin
case WaitForData(3*60*1000{ConnectionTimeout}) of
wrSignaled:
begin
try
Command := Receiveln;
Operation := UpperCase(CmdParamStr(Command, 0)); if Operation = 'QUIT' then
break
else if Operation = 'HELLO' then
Sendln('WORLD');
...
except
// on e: Exception do
end; FLastActivity := Now;
end; wrTimeout: break;
wrError: break;
end;
end;
finally
CoUninitialize;
end;
end;// 这个是分析来的命令, 一般格式是 COMMAND PARAMETERS, 跟 ParamStr 功能相近
function TTCPCollectorThread.CmdParamStr(Command: string; Index: Integer): string;
var
ps, pe: PChar;
len: Integer;
begin
result := ''; pe := PChar(Command);
ps := pe; while pe^ <> #0 do
begin
Inc(pe, 1); if pe^ = ' ' then
begin
if Index = 0 then
begin
len := pe - ps;
SetLength(result, len);
Move(ps^, PChar(result)^, len);
break;
end
else
begin
Dec(Index, 1);
Inc(pe, 1);
ps := pe;
end;
end;
end; if (pe^ = #0) and (ps <> pe) and (Index = 0) then
begin
len := pe - ps;
SetLength(result, len);
Move(ps^, PChar(result)^, len);
end;
end;const
CRLF = #13#10; // 加在全局function Sendln(s: string; const eol: string = CRLF): Integer; // 加在线程里function TManagementThread.Sendln(s: string; const eol: string): Integer;
begin
s := s + eol;
Result := ClientSocket.SendBuf(pchar(s)^, length(s));
end;
function TManagementThread.Receiveln(const eol: string): string;
var
len: Integer;
buf: array[0..2100] of char;
eolptr: pchar;
begin
Result := '';
eolptr := nil;
repeat
if WaitForData(1*60*1000{OperationTimeout}) <> wrSignaled then
begin
result := 'QUIT'; // 当作退出
exit;
end; len := ClientSocket.PeekBuf(buf, sizeof(buf) - 1);
if len > 0 then
begin
buf[len] := #0;
eolptr := strpos(buf, pchar(eol));
if eolptr <> nil then
len := eolptr - buf + length(eol);
ClientSocket.ReceiveBuf(buf, len);
if eolptr <> nil then
len := len - length(eol);
buf[len] := #0;
Result := Result + buf;
end; if len > 2100 then // command too long
raise Exception.Create('SEInvalidDataPacket'); until (len < 1) or (eolptr <> nil);
end;
试试 HELLO