第一次使用TTcpServer和TTcpClient这两个组件,出现了很奇怪的问题。
首先TTcpClient的BlockMode属性为bmBlocking.与TTcpClient建立连接后用Sendln()方法发送数据。如
TcpClient1.Sendln('1');TTcpServer端的BlockMode属性为bmThreadBlocking.它的OnAccpet方法如下:
procedure TForm1.Server1Accept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
textAll,text: String;
begin
text := ClientSocket.Receiveln ;
while Trim(text)<>''do
begin
textAll := textAll + Trim(text);
text := ClientSocket.Receiveln;
end;
if Trim(textAll)<>'' then
begin
if Length(Trim(textAll))>1 then
Application.MessageBox('不能一次发送多条指令','提示',MB_OK)
else
case StrToInt(textAll) of
1: CloseSystem;
else
ShowMessage('异常');
end;
end;
end;CloseSystem是我自定义的一个关机的方法。现在出现的问题为:
客户端与服务器能成功连接,在客户端用Sendln()方法发送数据'1'后,服务器端却没有响应。但是若此时先关闭客户端,不关闭服务器端,服务器端即会执行该关机的方法自动关机。
为什么我关闭客户端后服务器端才能执行相应的方法呢?
首先TTcpClient的BlockMode属性为bmBlocking.与TTcpClient建立连接后用Sendln()方法发送数据。如
TcpClient1.Sendln('1');TTcpServer端的BlockMode属性为bmThreadBlocking.它的OnAccpet方法如下:
procedure TForm1.Server1Accept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
textAll,text: String;
begin
text := ClientSocket.Receiveln ;
while Trim(text)<>''do
begin
textAll := textAll + Trim(text);
text := ClientSocket.Receiveln;
end;
if Trim(textAll)<>'' then
begin
if Length(Trim(textAll))>1 then
Application.MessageBox('不能一次发送多条指令','提示',MB_OK)
else
case StrToInt(textAll) of
1: CloseSystem;
else
ShowMessage('异常');
end;
end;
end;CloseSystem是我自定义的一个关机的方法。现在出现的问题为:
客户端与服务器能成功连接,在客户端用Sendln()方法发送数据'1'后,服务器端却没有响应。但是若此时先关闭客户端,不关闭服务器端,服务器端即会执行该关机的方法自动关机。
为什么我关闭客户端后服务器端才能执行相应的方法呢?
遇到回车才能返回的,或者有足够多的数据才能返回,否则,一直阻塞状态。所以你发送数据'1'后,text:=ClientSocket.Receiveln ; 已经读出
while trim(text)<>'' do
begin
...
text:=ClientSocket.ReceiveLn;///会一直阻塞在这里直到客户端关闭
end;客户端关闭后就执行了下面的代码,然后关机。
服务器端程序:procedure TfrmMain.TcpServerAccept(Sender: TObject;
ClientSocket: TCustomIpClient);
const
BUFFER_SIZE = 255;
var
S: string;
Buffer: array[0..BUFFER_SIZE - 1] of Char;
i: Integer;
Mem: TMemoryStream;
begin
Mem := TMemoryStream.Create;
try
repeat
i := ClientSocket.ReceiveBuf(Buffer, BUFFER_SIZE);
Mem.Write(Buffer, i);
until i < BUFFER_SIZE;
SetLength(S, Mem.Size);
if Length(S) > 0 then
begin
Move(Mem.Memory^, S[1], Length(S));
ShowMessageFmt('IP=%s; Content=%s', [ClientSocket.LocalHostAddr, S]);
end;
finally
Mem.Free;
end;
end;
客户端procedure TForm1.Button1Click(Sender: TObject);
var
S: String;
begin
S := 'procedure TForm1.Button1Click(Sender: TObject);';
TcpClient.SendBuf(S[1], Length(S));
end;
我遇到过同样的问题,这个也许可以帮你
ClientSocket: TCustomIpClient);
var
textAll,text: String;
begin
text := ClientSocket.Receiveln ;
while Trim(text) <>''do
begin
if Trim(text) <>'' then
begin
if Length(Trim(text))>1 then
//Application.MessageBox('不能一次发送多条指令','提示',MB_OK)//这里不能使用MessageBox,因为这是在子线程当中执行的
else
case StrToInt(text) of
1: CloseSystem;
else
//ShowMessage('异常'); //子线程也不能使用ShowMessage
end;
end;
text := ClientSocket.Receiveln;
end; end;