我想编写一个函数getDataFormSerevr(command:string):string;
函数实现的是:用TCP/IP通讯,向服务端发送command,并从服务端获得返回数据作为函数的值.
如何处理等待数据返回的问题?
如何解决超时问题?
希望高手提供解答.
函数实现的是:用TCP/IP通讯,向服务端发送command,并从服务端获得返回数据作为函数的值.
如何处理等待数据返回的问题?
如何解决超时问题?
希望高手提供解答.
解决方案 »
- ShellExecute打印问题,老问题了啊,没有找到答案
- 为什么Pos会得到这样的结果?
- 如何用鼠标滚轮来控制dbgrid控件的水平滚动条?
- delphi的语句太长想续行怎么做呢,象VB的续行符 _
- 数据库问题,请各位高手帮小第一个小忙.
- 很菜的问题: 怎样获得系统信息?比如当前桌面分辨率.
- 新病毒!!!!大家小心!!!数量不断递增!!!现在你的机子都染了吧!!csdn有可能因此瘫痪!!!!
- 为啥那些招聘上写的都是要C,C++程序员?
- 以下代码报错:"Canvas does not allow drawing!",是怎么回事?
- 关于WebBrowser
- 怎么去掉重复多余的显示列
- 想写一个这样的程序 大家给点思路
另外,等待数据返回的话,需要用线程来发送和接受
unit RCUnit;interface
uses Windows, SysUtils, WinSock, ComObj, ScktComp,SConnect;type
ESocketConnectionError = class(Exception); TQiSocketTransport = class(TInterfacedObject)
private
FEvent: THandle;
FAddress: string;
FHost: string;
FPort: Integer;
FClientSocket: TClientSocket;
FSocket: TCustomWinSocket;
protected
{ ITransport }
function GetWaitEvent: THandle; stdcall;
function GetConnected: Boolean; stdcall;
procedure SetConnected(Value: Boolean); stdcall;
function Receive(WaitForInput: Boolean;Buffer:Pointer):Integer; stdcall;
function Send(Buffer:Pointer;Count:Integer): Integer; stdcall;
public
constructor Create;
destructor Destroy; override;
property Connected:Boolean read GetConnected write SetConnected;
property Host: string read FHost write FHost;
property Address: string read FAddress write FAddress;
property Port: Integer read FPort write FPort;
property Socket: TCustomWinSocket read FSocket write FSocket;
end;
implementation
const
SIG_EXCEPTION:Integer=$EEEEEEEE;
SIG_OK :Integer =$00000000;
ESocketReadError ='Socket read error.';
ENoAddress ='No address.'; var
hWinSock2: THandle; WSACreateEvent: function: THandle stdcall;
WSAResetEvent: function(hEvent: THandle): Boolean stdcall;
WSACloseEvent: function(hEvent: THandle): Boolean stdcall;
WSAEventSelect: function(s: TSocket; hEventObject: THandle; lNetworkEvents: Integer): Integer stdcall;
function CheckSignature(Sig:Integer):Boolean;
begin
if Sig=SIG_EXCEPTION then
Raise Exception.Create('Remote call error!')
else
Result:=True;
end;{ TQiSocketTransport }constructor TQiSocketTransport.Create;
begin
inherited Create;
FEvent := 0;
end;destructor TQiSocketTransport.Destroy;
begin
SetConnected(False);
inherited Destroy;
end;function TQiSocketTransport.GetWaitEvent: THandle;
begin
FEvent := WSACreateEvent;
WSAEventSelect(FSocket.SocketHandle, FEvent, FD_READ or FD_CLOSE);
Result := FEvent;
end;function TQiSocketTransport.GetConnected: Boolean;
begin
Result := (FSocket <> nil) and (FSocket.Connected);
end;procedure TQiSocketTransport.SetConnected(Value: Boolean);
begin
if GetConnected = Value then Exit;
if Value then
begin
if (FAddress = '') and (FHost = '') then
raise ESocketConnectionError.Create(ENoAddress);
FClientSocket := TClientSocket.Create(nil);
FClientSocket.ClientType := ctBlocking;
FSocket := FClientSocket.Socket;
FClientSocket.Port := FPort;
if FAddress <> '' then
FClientSocket.Address := FAddress else
FClientSocket.Host := FHost;
FClientSocket.Open;
end else
begin
if FSocket <> nil then FSocket.Close;
FSocket := nil;
FreeAndNil(FClientSocket);
if FEvent <> 0 then WSACloseEvent(FEvent);
FEvent := 0;
end;
end;function TQiSocketTransport.Receive(WaitForInput: Boolean;Buffer:Pointer):Integer; stdcall;var
RetLen, Sig, StreamLen: Integer;
P: Pointer;
FDSet: TFDSet;
TimeVal: PTimeVal;
RetVal: Integer;
bFirst: boolean;begin
Result := 0;
TimeVal := NIL;
FD_ZERO(FDSet);
FD_SET(FSocket.SocketHandle, FDSet);
if not WaitForInput then
begin
New(TimeVal);
TimeVal.tv_sec := 0;
TimeVal.tv_usec := 1;
end;
RetVal := select(0, @FDSet, nil, nil, TimeVal);
if Assigned(TimeVal) then
FreeMem(TimeVal);
if RetVal = SOCKET_ERROR then
raise ESocketConnectionError.Create(SysErrorMessage(WSAGetLastError));
if (RetVal = 0) then Exit; RetLen := FSocket.ReceiveBuf(Sig, SizeOf(Sig));
if RetLen <> SizeOf(Sig) then
raise ESocketConnectionError.Create(ESocketReadError);
CheckSignature(Sig);
RetLen := FSocket.ReceiveBuf(StreamLen, SizeOf(StreamLen));
if RetLen = 0 then
raise ESocketConnectionError.Create(ESocketReadError);
if RetLen <> SizeOf(StreamLen) then
raise ESocketConnectionError.Create(ESocketReadError);
P := Buffer;
if (StreamLen > 0) then WaitForSingleObject(FEvent, {INFINITE}60000);
bFirst := True; while StreamLen > 0 do
begin
RetLen := FSocket.ReceiveBuf(P^, StreamLen);
if RetLen = 0 then
begin
if not bFirst then
raise ESocketConnectionError.Create(ESocketReadError); bFirst := False;
end; if RetLen > 0 then
begin
Dec(StreamLen, RetLen);
Inc(Integer(P), RetLen);
end; if StreamLen > 0 then
begin
if (WaitForSingleObject(FEvent, {INFINITE}90000) = WAIT_OBJECT_0) then
begin
WSAResetEvent(FEvent);
end
else
begin
raise ESocketConnectionError.Create('Read Error Single Object Timeout');
end;
end; end;
if StreamLen <> 0 then
raise ESocketConnectionError.Create(ESocketReadError);
end;function TQiSocketTransport.Send(Buffer:Pointer;Count:Integer): Integer; stdcall;
var
Size:Integer;
begin
Result := 0;
Size:=Count;
if Size>0 then
begin
FSocket.SendBuf(Buffer^, Count);
end;
end;function LoadWinSock2: Boolean;
const
DLLName = 'ws2_32.dll';
begin
Result := hWinSock2 > 0;
if Result then Exit;
hWinSock2 := LoadLibrary(PChar(DLLName));
Result := hWinSock2 > 0;
if Result then
begin
WSACreateEvent := GetProcAddress(hWinSock2, 'WSACreateEvent');
WSAResetEvent := GetProcAddress(hWinSock2, 'WSAResetEvent');
WSACloseEvent := GetProcAddress(hWinSock2, 'WSACloseEvent');
WSAEventSelect := GetProcAddress(hWinSock2, 'WSAEventSelect');
end;
end;initialization
LoadWinSock2;
end.
ST:TQiSocketTransport
...
创建并连接服务器
..getDataFormSerevr(command:string):string
begin
ST.Send....
ST.Receive.......
end;