多服务器端,单客户端多线程与它们通讯,每个线程如何处理收发数据包 ( 积分: 200 )

  • 主题发起人 主题发起人 eachbuilder
  • 开始时间 开始时间
E

eachbuilder

Unregistered / Unconfirmed
GUEST, unregistred user!
多服务器端(20个),单客户端多线程与它们通讯,每个线程连接一个服务器端,线程如何处理收发数据包,现用ICS的WSocket
TClientThread = class(TThread)
private
FWSocket: TWSocket;
FRcvBuf : string;
procedure FWSocketSessionConnected(Sender: TObject; Error: Word);
procedure FWSocketSessionClosed(Sender: TObject; Error: Word);
procedure FWSocketDataAvailable(Sender: TObject; Error: Word);
protected
procedure Execute; override;
public
constructor Create();
destructor Destroy; override;
end;

constructor TClientThread.Create;
begin
FreeOnTerminate:= True;
inherited Create(False);
end;

procedure TClientThread.Execute;
begin
FWSocket := TWSocket.Create(nil);
FWSocket.MultiThreaded := True;
FWSocket.Proto := 'tcp';
FWSocket.Port := '6706';
FWSocket.Addr := 'localhost';
FWSocket.LineMode := True;
FWSocket.LineEnd := #13#10;
FWSocket.OnSessionConnected := FWSocketSessionConnected;
FWSocket.OnSessionClosed := FWSocketSessionClosed;
FWSocket.OnDataAvailable := FWSocketDataAvailable;

FWSocket.Connect;
FWSocket.MessageLoop;
FWSocket.Destroy;
end;

procedure TClientThread.FWSocketSessionConnected(Sender: TObject; Error: Word);
begin
FWSocket.SendStr('Hello' + #13 + #10);
end;

procedure TClientThread.FWSocketSessionClosed(Sender: TObject; Error: Word);
begin
FWSocket.Release;
FWSocket:= nil;
end;

procedure TClientThread.FWSocketDataAvailable(Sender: TObject; Error: Word);
var
Buffer: array [0..4095] of Char;
Count : Integer;
begin
Count:= FWSocket.Receive(@Buffer, SizeOf(Buffer));
if (Count > 0) then
begin
if Buffer[0] = 'K' then
begin
FWSocket.SendStr('OK' + #13 + #10);
end
else begin
FWSocket.Send(@Buffer, Count);
end;
... //还有好多命令
end;
end;

destructor TClientThread.Destroy;
begin
if Assigned(FWSocket) then FWSocket.Close;

inherited;
end;

因为我是客户端,我要在主线程(MainFrm)里主动发送请求数据,然后服务器端响应,返回数据。
可是怎么发呢?还有,我现在是开一个线程连接一个服务器端,如何区分不同的服务器端的发送和接收?
 
多服务器端(20个),单客户端多线程与它们通讯,每个线程连接一个服务器端,线程如何处理收发数据包,现用ICS的WSocket
TClientThread = class(TThread)
private
FWSocket: TWSocket;
FRcvBuf : string;
procedure FWSocketSessionConnected(Sender: TObject; Error: Word);
procedure FWSocketSessionClosed(Sender: TObject; Error: Word);
procedure FWSocketDataAvailable(Sender: TObject; Error: Word);
protected
procedure Execute; override;
public
constructor Create();
destructor Destroy; override;
end;

constructor TClientThread.Create;
begin
FreeOnTerminate:= True;
inherited Create(False);
end;

procedure TClientThread.Execute;
begin
FWSocket := TWSocket.Create(nil);
FWSocket.MultiThreaded := True;
FWSocket.Proto := 'tcp';
FWSocket.Port := '6706';
FWSocket.Addr := 'localhost';
FWSocket.LineMode := True;
FWSocket.LineEnd := #13#10;
FWSocket.OnSessionConnected := FWSocketSessionConnected;
FWSocket.OnSessionClosed := FWSocketSessionClosed;
FWSocket.OnDataAvailable := FWSocketDataAvailable;

FWSocket.Connect;
FWSocket.MessageLoop;
FWSocket.Destroy;
end;

procedure TClientThread.FWSocketSessionConnected(Sender: TObject; Error: Word);
begin
FWSocket.SendStr('Hello' + #13 + #10);
end;

procedure TClientThread.FWSocketSessionClosed(Sender: TObject; Error: Word);
begin
FWSocket.Release;
FWSocket:= nil;
end;

procedure TClientThread.FWSocketDataAvailable(Sender: TObject; Error: Word);
var
Buffer: array [0..4095] of Char;
Count : Integer;
begin
Count:= FWSocket.Receive(@Buffer, SizeOf(Buffer));
if (Count > 0) then
begin
if Buffer[0] = 'K' then
begin
FWSocket.SendStr('OK' + #13 + #10);
end
else begin
FWSocket.Send(@Buffer, Count);
end;
... //还有好多命令
end;
end;

destructor TClientThread.Destroy;
begin
if Assigned(FWSocket) then FWSocket.Close;

inherited;
end;

因为我是客户端,我要在主线程(MainFrm)里主动发送请求数据,然后服务器端响应,返回数据。
可是怎么发呢?还有,我现在是开一个线程连接一个服务器端,如何区分不同的服务器端的发送和接收?
 
借贵宝地用一下,我正在做一个银行接口程序,用DELPHI服务端(TServerSocket),客户端(TClientSocket)希望服务端用多线程处理客户端连接、接受客户端数据、返回数据给客户端。各位大虾,能给与思路,最好有代码帖子。先谢谢了
 
emailqjc,你的情况跟我不一样,你的情况是常见的,可以查以往帖子
 
我想这需要你设置一个数据结构.比如
TDataRec = record
ThreadID : DWORD;
...
PData : POINTER;
end;
然后根据 生产/消费 模式来处理数据.如果是发送数据.由主程序申请内存,填充数据,然后把TDataRec传递给线程对象.在线程对象当中使用数据/释放内存.
如果你对DIrectShow有基本的了解,便很容易理解.
至于接收数据,因为不晓得你对数据需要怎样的处理.不过一个原则是尽可能地把工作放到线程中去执行.传递数据类似上边.
你可以使用一个对象封装上边的功能.类似于一个FIFO的线程安全的队列
 
谢谢zjan521
“在线程对象当中使用数据/释放内存”,我现在就是不知道如何在线程对象当中使用数据,ICS的WSocket是异步非阻塞型的,TClientThread.Execute里用FWSocket.MessageLoop
作消息循环,我想是不是在TClientThread.FWSocketDataAvailable事件里使用?可是这个
事件不会主动触发,只能是接收服务器端数据,望给段实例代码,谢谢!
 
“至于接收数据,因为不晓得你对数据需要怎样的处理.不过一个原则是尽可能地把工作放到线程中去执行.传递数据类似上边.”,接收完数据,我要返回主线程,另开一个线程写入数据库的,并且界面显示,所以我觉得zjan521的思路很好,作一个线程安全的队列,负责进出。问题是我搞不懂在ICS里如何在线程对象当中使用数据
 
使用数据.
TDataRec = record
ThreadID : DWORD;
...
PData : POINTER;
end;
使用TDataRec.PData来保持数据.你只需要把TDataRec通过某种形式传递过去,仁厚使用PData即可访问数据.你也可以优化性能,采用固定大小的内存块池.因为直接使用的话可能需要涉及线程安全/释放等操作,比较复杂,容易出错.因此最好能够用对象封装.
如果还不放心,也可以使用支持接口的对象封装.比如TInterfacedObject/TStreamAdapter.
要记得.在同一进程当中,内存空间是共享的.不过不同的内存管理器未必是针对整个线程的.
 
zjan521,“使用PData即可访问数据”,现在的问题是我不知道在哪个事件里访问?
TClientThread.Execute?或者TClientThread.FWSocketDataAvailable?还是其他的?能否给点代码啊,谢谢!
 
我对ICS不熟悉,因此具体那个事件/什么时候,我也不是很清楚.
不过TWSocket.ProcessMessages你可以参考.
(while not terminated do
{
TWSocket.ProcessMessages;
if there has Data then
{PROCESS THE DATA}
})
而且直接使用TWSocket.MessageLoop我想应该是没有办法支持TThread.Terminated的
 
请熟悉多线程和ICS的高手进来帮忙
 
服务端是非阻塞发送包,那么客户端可以用线程来接收数据吗?客户端可能接收大数据包,在解析包时,能否使用线程呢??
 
hjp0214,可以
 

Similar threads

后退
顶部