TClientSocket与TServerSocket的同步问题(100分)

  • 主题发起人 主题发起人 cequal
  • 开始时间 开始时间
C

cequal

Unregistered / Unconfirmed
GUEST, unregistred user!
本人使用TClientSocket与TServerSocket进行网络通讯,如果取
缺省设置的话,将会使用Delphi的事件进行通讯。
比如:你需要在OnRead事件中响应接收对方信息。
但是,现在我需要进行同步通讯,也就是一应一答的方式,在DELHPI中可以
设置TClientType或TServerType。不知有那位高手做过这方面的工作。
欢迎指教
<a href = "mailto:cequal@163.net">电子邮件地址:cequal@163.net
</a>
 
利用Multi Thread,参见 WaitForData的Delphi帮助,目前我正在试验中,还
不很清楚
 
ClientType = ctBlocking;
ServerType = stBlocking;
 
我也想听听
 
同步指的是什么意思?
 
cequal老兄:
接您的宝地一用,使用TClientSocket与TServerSocket进行网络通讯.
要求server端收到数据后并完成相应的操作后再同志client端,传送下一段数据
按说tcp协议提供了流量控制,但我在实际操作过程中如果取数据的操作比较慢时
只能传送一批数据.
我想采用一问一答得的方式,来同步传输和处理.
我想和您的问题差不多,因此借您的宝地一用.我也出100分.
希望大家能解答.
 
1.将clientsocket的clienttype设为ctblocking,将serversocket的servertype
设为stThreadBlocking
2.将clientsocket的host和port设为serversocket的IP和端口号
3.自定义线程tdealthread:
TdealThread = class(TServerClientThread)
private
protected
procedure Execute; override;
public
thr:tserverclientwinsocket;
end;
4.在serversocket的serversocketgetthread事件中写入以下语句以便在接到clientsocket
端请求时启动tdealthread线程:
var
myt:tdealthread;
begin
myt:=tdealthread.Create(false,clientsocket) ;
myt.thr :=clientsocket;
socketthread:=myt;
end;
5.在serversocket的procedure TdealThread.Execute中写入每次接到clientsocket请求
时想要完成的动作,举例如:
var
mysockets:twinsocketstream;
rcvbuffer:array[0..299] of char;
sndbuffer:array[0..299] of char;
begin
mysockets:=twinsocketstream.Create (thr,20);
mysockets.WaitForData (1000);
mysockets.Read (rcvbuffer,300);//将client端数据取到rcvbuffer中
//......数据处理,将要发往client端的数据放到sndbuffer中
mysockets.WaitForData (1000);
mysockets.Write(sndbuffer,300);
end;
6.在客户端需要向服务器端提出请求时,执行下面程序:
var
myclientsockets:twinsocketstream;
rcvbuffer:array[0..299] of char;
sndbuffer:array[0..299] of char;
begin
clientsocket.active:=true;
myclientsockets:=twinsocketstream.Create (clientsocket.socket,20);
myclientsockets.WaitForData (1000);
//......将要传送的数据放入sndbuffer中
myclientsockets.write(sndbuffer,300);
myclientsockets.WaitForData (1000);
myclientsockets.read(rcvbuffer,300);//将serversocket发回的数据取到rcvbuffer中
clientsocket.active:=false;
end;
基本框架就是这样了,当然别忘了打开serversocket.



 
仅为上一位老兄加一点补充:
1.在自定义的线程中最好有循环处理过程:
vStream := TWinSocketStream.Create(ClientSocket, ConnectTimeOut);
while (not Terminated) and ClientSocket.Connected do
begin
//接收报文
....
//发送应答
.....
if ... then
ClientSocket.Close;
end;
ClientSocket.Close;
vStream.Free;
//接收和应答报文的格式自定义,可参考TCP/IP的实现方法

2.在应答前,最好有一小段延时,避免过分频繁的交换数据导致死机
sleep(..)

 
why you like synchronize mode as you can use asynchronize mode?
I think it is not wise. you can use state machine to control send and reply, it is easier and more reliable.
 
一问一答的实现:

1.将Server和Client都设成阻塞式的
2.(Server和Client同)

while(1)
{
Read_Data_From_Socket();
Process_Data();
Send_Data();
}

3.Client需要加一个初始化循环的:
Send_Data();
 
水赐源程序?
yunfengli@hotmail.com
 
服务端如下:(以下因只来回传数据一次,故没用while)
procedure TMyServerThread.ClientExecute;
var
Stream : TWinSocketStream;
Buffer : array[0 .. 2047] of Char;
Answer: String;
aaa: array [0..9] of char;
begin
Answer:='Content-type: TEXT/HTML'#13#10#13#10+'<HTML><HEAD><TITLE>'#13#10;
Answer:=Answer+'Hello Word'#13#10'</TITLE></HEAD><BODY> aaa </BODY></HTML>'#13#10;
aaa:='11111';
// while (not Terminated) and ClientSocket.Connected do
if ((not Terminated) and ClientSocket.Connected) then
begin
try
Stream := TWinSocketStream.Create(ClientSocket, 3000);
try
FillChar(Buffer, 2047, 0);
if Stream.WaitForData(3000) then
begin
if Stream.Read(Buffer, 2048) = 0 then
ClientSocket.Close;
// if strLcomp(aaa,Buffer,1)=0 then
if Stream.WaitForData(1000) then
Stream.Write(Answer,Length(Answer)+1);
end
else
ClientSocket.Close;
finally
Stream.Free;
end;
except
//HandleException;
end;
end;
end;

客户端如下:
procedure TClientForm.Button1Click(Sender: TObject);
var
TheStream: TWinSocketStream;
buffer: array [0..9] of char;
buffer1: array [0..126] of char;
begin
buffer:='11111';
FillChar(Buffer1, 127, 0);
ClientSocket1.Open;
TheStream := TWinSocketStream.Create(ClientSocket1.Socket, 3000);
try
if ClientSocket1.Active then
begin
// if TheStream.WaitForData(3000) then
TheStream.Write(buffer, Length(buffer) + 1);
if TheStream.WaitForData(60000) then
begin
if TheStream.Read(buffer1,30)=0 then
ClientSocket1.Close
else
StatusBar1.Panels[1].Text:=buffer1;
end;
end;
finally
TheStream.Free;
end;
ClientSocket1.Close;
end;

这段程序执行时服务端Read时数据正确,而之后的客房端Read的数据不正确
请问各位大侠 why?
有哪位大侠能给小D一个完整的例子,小D愿大出血 300分!!!
EMail to:<a href = "mailto:zaoya@163.net">zaoya@163.net
 
小D正在做一个实时监控程序,Client(Brower)发出请求,Server(NT下一Service)Listering,接到请求,则启动一线程从某监测点取实时数据,并送回到Client。
若Client每隔1秒发一请求,则Server是否只能做到每次启动一线程来传送实时数据,传送完成后结束线程,能否做到对一个客户只产生一个线程,并保持Connection不断开以备下次传输,怎样做?
若Client只发一次请求,则Server要求不断发送实时数据,并能监视Connection是否正常,如不正常(如断开),则怎样与Client重新connect,
并继续传输数据?这样,是否要定义一个用户协议让Client发断开消息?
很急,先在此谢谢各位大侠的帮助!!!
 
小D正在做一个实时监控程序,Client(Brower)发出请求,Server(NT下一Service)Listering,接到请求,则启动一线程从某监测点取实时数据,并送回到Client。
若Client每隔1秒发一请求,则Server是否只能做到每次启动一线程来
传送实时数据,传送完成后结束线程,能否做到对一个客户只产生一个线程
,并保持Connection不断开以备下次传输,怎样做?
若Client只发一次请求,则Server要求不断发送实时数据,并能监视
Connection是否正常,如不正常(如断开),则怎样与Client重新connect,
并继续传输数据?这样,是否要定义一个用户协议让Client发断开消息?
是否要用TServerSocket&TClientSocket?如不用,可有什么好办法?有
哪位大侠能给小D一个完整的例子.
很急,先在此谢谢各位大侠的帮助!!!
 
1、你的程序有点小问题,string的第一个字节表示的是长度,
你从第一个字节接收,当然出错。
2、至于监听程序的服务器端可用前面提供的循环结构处理,客
户端相反,用延时或挂起、激活的手段实现间隔发送。
3、client和server的线程是一一对应的,只要一方中断,另一
方会引发异常,截获并处理之即可实现中断连接。然后再由客户端
重发请求再次建立新连接。

 
接受答案了.
 
为什么TServerSocket是阻塞的,而TClientSocket是非阻塞的时候
连接的速度特别慢,大约30s
注:TServerSocket的例子从http://www.vxlxx.com(深度历险)中download,
TClientSocket的例子是Delphi4自带的Chat
 

Similar threads

后退
顶部