阻塞模式常用在单通道Server自动响应收发数据里面,比如ClientA向ServerB发送报文,并且ClientA只需要它发送的这条数据ServerB对它有一个响应。其实c++ builder 里面阻塞模式的收发数据主要理解TWinSocketStream这个流。
void __fastcall TForm1::btn_1Click(TObject *Sender) { //1.初始化一些socket参数 ClientSocket1->Address="127.0.0.1"; ClientSocket1->Port=10101; ClientSocket1->ClientType=ctBlocking;//此处表示socket是阻塞模式 int TIMEOUT=300000,MAXLENGTH=1024; TWinSocketStream *pClientStream;//TWinSocketStream to read or write information over a blocking socket connection pClientStream=new TWinSocketStream(ClientSocket1->Socket,TIMEOUT); //2.连接Server端 ClientSocket1->Open(); //3.发送数据 char sendBuf[1024]; int sendCount=0; strcpy(sendBuf,E_send->Text.c_str()) ; sendCount=pClientStream->Write(sendBuf,strlen(sendBuf)+1); if(sendCount==0) ShowMessage("发送失败!"); //4.接收数据 char receiveBuf[1024]; int Len=0; if (pClientStream->WaitForData(TIMEOUT)) //在TIMEOUT时间内如果没有接收到数据程序是直会在此挂起,因此如果阻塞模式接收数据的话一般放在线程里面 Len=pClientStream->Read(receiveBuf,MAXLENGTH); receiveBuf[Len]=0; Memo1->Lines->Add(receiveBuf); }
使用多线程的阻塞模式要从一个TServerClientThread对象中派生一个类,在类的execute()方法中写收发数据的代码。收数据一般通过TWinSocketStream流实现。
这是派生的类的代码头
//--------------------------------------------------------------------------- #ifndef UnitServerThreadH #define UnitServerThreadH //--------------------------------------------------------------------------- #include <ScktComp.hpp> #include <StdCtrls.hpp> #include "UnitMain.h" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- class TServerThread : public TServerClientThread { protected: void __fastcall ClientExecute(void); int __fastcall ReadStr(char * buf); public: __fastcall TServerThread(bool CreateSuspended, TServerClientWinSocket* ASocket,HWND hWnd); __fastcall ~TServerThread(); private: TWinSocketStream *pStream; HWND m_hwnd; }; #endif
//cpp文件
#include <vcl.h> #pragma hdrstop #include "UnitServerThread.h" //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- __fastcall TServerThread::TServerThread(bool CreateSuspended, TServerClientWinSocket* ASocket,HWND hWnd) : TServerClientThread(CreateSuspended,ASocket) { m_hwnd=hWnd; FreeOnTerminate=false; } //--------------------------------------------------------------------------- void __fastcall TServerThread::ClientExecute(void) {//当一个客户连接的时候进入ClientExecute //1.接收数据 try { pStream=new TWinSocketStream(ClientSocket,60000); char buf[1024]; memset(buf,0,sizeof(buf)); try { int len=0; if(pStream->WaitForData(60000)) { len=pStream->Read(buf,1024); buf[len]=0; } } catch(Exception &E) { } //2.发送数据 ClientSocket->SendText("已经收到消息!消息为"+AnsiString(buf)); } __finally { ClientSocket->Close(); delete pStream; } }
下面是主窗口代码
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "UnitMain.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ServerSocket1->Port=10101; ServerSocket1->ServerType=stThreadBlocking; //设置为阻塞模式 //指定缓存使用的线程的个数:如果第一个Client连接Server会自动生成一个TServerThread类对象 //当这个客户端断开时,这个对象不会释放,当第二个Cliet连接时,会重用这个TServerThread而不是 //重新创建此对象。ThreadCacheSize实际上指线程类不被释放的个数。 ServerSocket1->ThreadCacheSize=10; // ServerSocket1->Open() ; } //--------------------------------------------------------------------------- void __fastcall TForm1::ServerSocket1GetThread(TObject *Sender, TServerClientWinSocket *ClientSocket, TServerClientThread *&SocketThread) { SocketThread=new TServerThread(false,ClientSocket,Form1->Handle); } //---------------------------------------------------------------------------