📄 bcb_n15.htm
字号:
connections在等待通过连接读或写信息完成时挂起了其他代码的执行,服务器socket控件通常产生一个新的执行线程给每一个客户连接,当ServerType设置为stThreadBlocking时.许多使用Blocking连接的应用都写使用线程(using
threads.甚至如果你不使用线程,你可能也想使用(using) TWinSocketStream去读和写. <br>
1)using threads <br>
当使用一个blocking connection进行读或写操作时,客户sockets不会自动产生一个新线程.如果你的客户应用程序没有什么事做,直到读或写信息完成,那么这正是你想要的.如果你的应用包括了一个用户界面,它还需要响应用户的操作,那么,你可能想产生一个独立的线程去读写.当服务器sockets形成一个blocking连接时,他们常常产生独立的线程给每一个客户连接,所以没有客户需要等待直到其他客户完成通过连接读或写操作.在默认情况下,服务器sockets使用TServerClientThread对象去实现为每个连接执行不同的线程.
<br>
TServerClientThread对象模拟发生在non-blocking连接中的OnClientRead和OnClientWrite事件.可是,这些事件发生在监听socket上时,不是本地线程(thread-local).如果客户请求频繁,你将想建立你自己的TServerClientThread子类去提供一个安全线程(Thread-Safe)去完成读和写操作.
<br>
当写客户线程或写服务器线程时,你能够使用TwinSocketStream去做实际的读写操作. <br>
A)写客户端线程 <br>
为客户端连接写一个线程,定义一个新线程对象,使用新线程对象对话框.你的新线程对象Execute方法的句柄的通过线程连接进行读写操作的细节,可以建立一个TWinSocketStream对象,然后使用它来读或写.
<br>
使用你自己的线程,在OnConnect事件句柄中建立它.关于建立和运行线程的更多信息,请看Executing thread objects.
<br>
例子:这个例子显示一个应用的客户线程在连接确定后向服务器发出写请求. <br>
void __fastcall TMyClientThread::Execute() <br>
{ <br>
while (!Terminated && ClientSocket1->Active) <br>
// make sure connection is active <br>
{ <br>
try <br>
{ <br>
TWinSocketStream *pStream = new TWinSocketStream(ClientSocket1.Socket,60000);
<br>
try <br>
{ <br>
char buffer[10]; <br>
GetNextRequest(buffer); <br>
// GetNextRequest must be a thread-safe method <br>
// write a request to the server <br>
pStream->Write(buffer,strlen(buffer) + 1); <br>
// continue the communication (eg read a response) <br>
<br>
} <br>
__finally <br>
<br>
{ <br>
delete pStream; <br>
} <br>
} <br>
catch (Exception &E) <br>
{ <br>
if (!E.ClassNameIs("EAbort")) <br>
Synchronize(HandleThreadException()); <br>
// you must write HandleThreadException <br>
} <br>
} <br>
} <br>
<br>
B)写服务器线程 <br>
服务器连接线程由TServerClientThread派生.因为这个,不能使用新线程对象对话框.替代的,手动声明你的线程如下: <br>
<br>
class PACKAGE TMyServerThread : <br>
public ScktComp::TServerClientThread <br>
{ <br>
public <br>
void __fastcall ClientExecute(void); <br>
} <br>
<br>
注意你将用重载ClientExcute方法替代Execute方法.执行ClientExecute方法必须为客户端连接写一个同样的Execute方法线程.然而,当你从控件栏上放一个客户socket控件到你的应用上时来替代这个方法时.监听服务socket同意一个连接时,服务客户线程必须使用TServerClientWinSocket对象来建立.这可以利用共公共的CientSocket属性.另外,你能够使用HandleException这个protected性的方法,胜过
<br>
你自己写你的thread-safe例外操作. <br>
<br>
警告:Server sockets会缓存他们使用到的线程.确信ClientExecute方法执行一些必要的初始化操作,以便它们在最后执行时不致于产生不利的结果.
<br>
<br>
当你使用你的线程时,在OnGetThread事件句柄中建立它.当建立线程,设置CreateSuspended参数为false. <br>
例子:这个例子显示一个为一个应用服务的线程,这个应用是在连接确定后由客户端来的读请求. <br>
<br>
void __fastcall TMyServerThread::ClientExecute() <br>
{ <br>
while (!Terminated && ClientSocket->Connected) <br>
// make sure connection is active <br>
{ <br>
try <br>
{ <br>
TWinSocketStream *pStream = new TWinSocketStream(ClientSocket, <br>
60000); <br>
try <br>
{ <br>
char buffer[10]; <br>
memset(buffer, 0, sizeof(buffer)); <br>
if (pStream->WaitForData(60000)) <br>
// give the client 60 seconds to start writing <br>
{ <br>
if (pStream->Read(buffer, sizeof(buffer) == 0) <br>
<br>
ClientSocket->Close(); <br>
// if can't read in 60 seconds, close the connection <br>
// now process the request <br>
} <br>
else <br>
ClientSocket->Close(); <br>
} <br>
__finally <br>
<br>
{ <br>
delete pStream; <br>
} <br>
} <br>
catch (...) <br>
{ <br>
HandleException(); <br>
} <br>
} <br>
} <br>
<br>
C.使用TwinSocketStream <br>
当为一个blocking连接实现一个线程时,你必须确定在连接的另一端的socket是准备写还是读.Blocking连接不会通知socket当它准备好写或读操作的时候.想看看连接是否准备好,使用TWinSocketStream对象.TWinSocketStream提供一个方法去帮助调整读或写操作时间的选择.调用WaitForData方法去等待,直到socket另一端的
<br>
准备好写操作.当读写操作使用TWinSocketStream时,如果读或写操作在指定的时间期限内未能完成,Stream将发生超时.这个超时被当作一个结果,socket应用不会暂停,而是不断的通过一个dropped
connection试图读或写. <br>
<br>
注意:你不能在non-blocking连接中使用TWinSocketStream <br>
</p>
</td>
</tr>
</table>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -