请教Socket的Blocking和NonBlocking模式与多线程搭配的问题(100分)

  • 主题发起人 主题发起人 yeow
  • 开始时间 开始时间
Y

yeow

Unregistered / Unconfirmed
GUEST, unregistred user!
我在此只讨论客户端的问题

客户端Socket有两种模式:
Blocking阻塞方式,是指读写端口的时候是同步进行的,未完成读写前不能在该端口上收发数据(端口处于阻塞状态)。可以理解为半双工。
NonBlocking非阻塞方式,是指读写端口的时候是异步进行的,读写指令会立即返回,不会引起端口阻塞,可以理解为全双工。

我现在正在写一个Socket客户端程序,服务器端允许多连接,数据交换是采用应答方式的。但是允许一次性发送多条请求而不必死死的等待回应才能发下一条请求。回应是异步回复的。所以我很自然的就用NonBlocking方式了。刚开始用的是单TCP连接,收发都很正常,但是速度(吞吐量)上不去。所以就要用多TCP连接方式并行发送请求了。我选择多线程(每个线程内一个TCP连接)并行发送,Socket模式还是采用NonBlocking。问题就来了:在线程内部不能正常打开TCP连接!代码如下:
代码:
type
  TMyThread = class()
  private
    FClientSocket: TClientSocket;
    procedure SocketConnect(Sender: TObject; Socket: TCustomWinSocket);
  protected
    procedure Execute(Sender: TObject); override;
  public
    constructor Create;
    // ...    
  end;
  
implementation

constructor TMyThread.Create;  
begin
  inherited Create(True); // Suspend
  FreeOnTerminate := False;
  
  FClientSocket := TClientSocket.Create(nil);
  with FClientSocket do
  begin // FRemoteIP是服务器的IP, FRemotePort是服务器的监听端口
    Address := FRemoteIP; 
    Port := StrToInt(FRemotePort);
    ClientType := ctNonBlocking;
    OnConnect := SocketConnect;
    // ...
  end;
  
  //...
  
  Resume;
end;
  
procedure TMyThread.Execute(Sender: TObject);
begin
  while not Terminated do
  begin
    // 打开TCP连接
    if not FClientSocket.Active then // 每次循环进来都未打开
    begin
      FClientSocket.Open;
      Sleep(300);
    end;
    
    // ...
  end;
end;  

procedure TMyThread.SocketConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin  // 该事件始终无法正常触发!
  // ...
end;

end;

在线程中我也不知道用什么方法能够“空等”,只好用Sleep()了。您能告诉我么?

我的理解(请指正):
1. 单连接可以用Blocking和NonBlocking中的任何一种,没有问题。
2. 多连接(多线程)就只能用Blocking了吗?
还是我的代码有问题?请指教,谢谢!
 
由于你是在线程里用的ClientSocket的非组塞模式,这样是不行的,
ClientSocket是消息模式的非组塞,在线程里是没有用的,他是通过
Application类分配消息的,建议你自己在线程里建立消息队列,不
过这样效率不高,还是用其他非组塞模式,消息模式是效率最底的
一种非组塞模式
 
张无忌兄,能详细说明一下其他非阻塞模式的实现方法么?
还有,我上面提到了,如何保证在线程内部实现“空等”,即不忙等,但是也能够触发该类
中成员的事件呢?多谢啦!
 
建议先去找几本winsock编程的书看看,
 
时间紧,我粗略的翻看过《TCP/IP 协议详解》,也看了Delphi内部TClientSocket的代码。
可是还是没能解决问题。
 
这个要一些SDK知识和基本的多线程支持才好对付,winsock太复杂了,模式很多
需要很长时间的学习和实践,
 
你的意思我明白,由于该线程占用了过多的时间检查ClientSocket的状态,但是
ClientSocket状态的转换是通过消息驱动的,而线程内部又没有消息循环,所以
那条发往ClientSocket的消息被简单的丢弃了。我的理解正确么?
 
对,最好的办法是自己在线程里建立一个消息队列,不过这样效率太低了,
 
为什么效率会低呢?是主线程和子线程的执行同步的影响么?
如果要建立消息队列的话,应该具体怎么办呢?对于本问题
可能不行,对于其他问题(多线程下的)可能就很有帮助了。
 
您能否推荐几本Winsock的书呢?
 
市面上书还是不不少的,一般如果ms出版社的出的书都可以考虑
 
用Delphi做Socket,调试真麻烦。我原来也是这样的一个项目。主要是做客户端的应用。
Delphi 不是掉包就是多发,乱码。
改用VC6++, 很快搞定。 真说不清其是怎么封装的
 
多人接受答案了。
 
后退
顶部