BCB建设基于Internet的点对点Chat
副标题#e#
建设基于Internet的应用措施,你也许会想到巨大的WinSock编程。不外,C++ Builder3提供了新的WebBroker的Internet套件,个中的TClientSocket和TServerSocket组件封装了Windows的有关API,大大简化了WinSock编程。要通过Internet传输数据,至少需要一对Socket,一个Socket在客户端,另一个Socket在处事器端。其实TClientSocket、TServerSocket组件并不是Socket工具,其属性Socket将返回各自的Socket工具。TClientSocket用来处理惩罚客户端随处事器端之间的socket毗连,TServerSocket用来处理惩罚由客户端发来的socket毗连,一旦客户端和处事器端都接通了socket,客户端和处事器端就可以彼此通信了。
成立一新项目,建设应用措施的用户界面:
1.将组件页切换到Internet页,放一个TServerSocket组件和一个TClientSocket组件到窗体上,这样应用措施既可以是TCP/IP处事器,也可以是TCP/IP客户。将Port属性都设为同一个值(如1000),确定Socket之间的毗连范例为NonBlocking(非阻塞方法)。
2.放两个TMemo组件到窗体上,用来别离显示两边的谈话内容,将Memo2的ReadOnly属性设为True。
3.在窗体的顶部放上一个Panel组件,在其上放三个按钮:监听(btnlisten)、毗连(btnconnect)、断开(btndisconnect),用来启动相应的操纵。
4.在窗体底部放一个StatusBar组件,将其SimplePanel属性设为True,在相应的事件处理惩罚措施中改变状态条信息,让用户随时相识毗连状态。
打开头文件,在窗体类的Private段添加两个私有成员: bool IsServer;String Server。两边通信时需同时运行Chat措施,IsServer用来确定哪个Chat措施处于处事器端,Server用来存放处事器的主机名。成立窗体类的结构器如下:
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
IsServer=false;
Server="localhost";
}
这里Server被缺省设为localhost,这样措施可以在没有连入Internet的单机长举办调试。在Windows子目次下你可以找到hosts.sam文件中,在该文件中已经将本机IP地点127.0.0.1界说了主机名:localhost。
void __fastcall TForm1::FormCreate(TObject *Sender)
{
btndisconnect- >Enabled=false;
}
措施运行后,假如用户按下"监听"钮,则将该措施设为处事器端,这时应将TServerSocket的Active属性设为True,使处事器自动进入监听状态。
void __fastcall TForm1::btnlistenClick(TObject *Sender)
{
ClientSocket1- >Active=false;
ServerSocket1- >Active=true;
StatusBar1- >SimpleText="正在监听...";
btnlisten- >Enabled=false;
btnconnect- >Enabled=false;
}
当用户按下"毗连"钮后,措施会弹出一个询问框,要求用户输入要毗连的处事器的主机名,然后成立毗连。
void __fastcall TForm1::btnconnectClick(TObject *Sender)
{
if(InputQuery("毗连随处事器","输入处事器地点:",Server)){
if(Server.Length() >0){
ClientSocket1- >Host=Server;
ClientSocket1- >Active=true;
btnlisten- >Enabled=false;
btnconnect- >Enabled=false;
btndisconnect- >Enabled=true;
}
}
}
当用户提出毗连请求后,客户端会触发OnCreate事件,措施先在状态条中显示毗连信息,然后将显示对方谈话内容的Memo2清空,筹备开始攀谈。
void __fastcall TForm1::ClientSocket1Connect(TObject *Sender,
TCustomWinSocket *Socket)
{
StatusBar1- >SimpleText="毗连到:"+Server;
Memo2- >Lines- >Clear();
}
#p#副标题#e#
在处事器接管了客户的请求后会触发OnAccept事件,在这个事件处理惩罚措施中将符号处事器端的变量IsServer设为True,并筹备开始攀谈。
void __fastcall TForm1::ServerSocket1Accept(
TObject *Sender,
TCustomWinSocket *Socket)
{
Memo2- >Lines- >Clear();
IsServer=true;
StatusBar1- >SimpleText="毗连到:"
+Socket- >RemoteAddress;
}
在成立毗连后,两边就可以在Memo1中输入谈话内容开始举办攀谈了,按下Enter键后,将地址行的文本发送出去。处事器端的Socket的Connections属性返回一个数组,该数组由处事器当前勾当的毗连构成。
void __fastcall TForm1::Memo1KeyDown(
TObject *Sender, WORD &Key,
TShiftState Shift)
{
if(Key==VK_RETURN){
if(IsServer)
ServerSocket1- >Socket- >Connections[0]- >SendText(
Memo1- >Lines- >Strings[Memo1- >Lines- >Count-1]);
else
ClientSocket1- >Socket- >SendText(
Memo1- >Lines- >Strings[Memo1- >Lines- >Count-1]);
}
}
#p#分页标题#e#
在本例中我们回收非阻塞传输方法,当个中的一方举办写操纵时,另一方会触发OnRead事件(客户端)或OnClientRead事件(处事器端),这两个事件的处理惩罚措施只是将吸收到的内容添加到Memo2的后头。
Memo2- >Lines- >Add(Socket- >ReceiveText());
假如在用户成立毗连后单击"断开"钮,将断开客户端与处事器的毗连,处事器端将触发OnClientDisconnect事件,而客户端则会触发OnDisconnect事件,这时处事器端应回到监听状态,期待用户的毗连;而客户端将返回到毗连前的状态,期待用户再次成立毗连,假如有不止一个处事器的话,可以选择毗连到其他的处事器上。
void __fastcall TForm1::btndisconnectClick(
TObject *Sender)
{
ClientSocket1- >Close();
}
void __fastcall TForm1::ServerSocket1ClientDisconnect(
TObject *Sender,
TCustomWinSocket *Socket)
{
StatusBar1- >SimpleText="正在监听...";
}
void __fastcall TForm1::ClientSocket1Disconnect(
TObject *Sender, TCustomWinSocket *Socket)
{
btnlisten- >Enabled=true;
btnconnect- >Enabled=true;
btndisconnect- >Enabled=false;
StatusBar1- >SimpleText="";
}
另外在客户端还应该增加错误捕捉机制,当用户输入无效的处事器名或处事器端没有处于监听状态时可以或许实时给用户反馈信息。
void __fastcall TForm1::ClientSocke
t1Error(TObject *Sender,
TCustomWinSocket *Socket,
TErrorEvent ErrorEvent, int &ErrorCode)
{
StatusBar1- >SimpleText="无法毗连到:
"+Socket- >RemoteHost;
ErrorCode=0;
}