一,认识C++Builder中的WinSock控件及其相关类
WinSock是一组用C语言写的API,用于通过Internet进行数据传输。通过WinSock编程可以获得更大的灵活性。编写WinSock应用程序本来是很麻烦的,不过,在C++ Builder 5.0中,您并不需要直接与WinSock中的API打交道,因为C++ Builder 5.0新增加了TClientSocket控件和TserverSocket控件,这两个控件封装了Windows的有关API,使得对WinSock的访问大大简化。用Socket 建立的连接是建立在TCP/IP协议基础上的,同时也支持其它相关的协议,如XNS、DECnet以及 IPX/SPX等。Socket的连接必须要建立有一个服务器端(Server)和一个客户端(Client)。在C++ Builder 5.0中分别用TClientSocket控件和TServerSocket控件来操纵客户端Socket与服务器端Socket的 连接和通信。这两个控件用于管理服务器和客户的连接,它们本身并不是Socket对象,操纵 Socket对象的是TCustomWinSocket及其派生类,如TClientWinSocket、TserverWinSocket . TServerClientWinSocket等。 Socket之间的连接可以分为三种类型:客户端连接、监听连接以及 服务器端连接,所谓客户端连接,是指由客户端的Socket提出连接请求,要连接的目标是服务 器端的Socket。为此,客户端的Socket必须首先描述它要连接的服务器端Socket(主要是指服务器 端Socket的地址和端口号),然后再定位所要连接的服务器端Socket,找到以后,就向服务器端 Socket请求连接。当然,服务器端的Socket此时未必正好处于准备好状态,不过,服务器端的 Socket会自动维护客户请求连接的队列,然后在它认为合适的时候向客户端Socket发出“允许连接” (Accept)的信号,这时客户端Socket与服务器端Socket的连接就建立了。所谓监听连接,服务器端 Socket并不定位具体的客户端Socket,而是处于等待连接的状态。当服务器端Socket监听到或者说 接收到客户端Socket的连接请求,它就响应客户端Socket的请求建立一个新的Socket句柄并与客户 端连接,而服务器端Socket继续处于监听状态,还可以接收其它客户端Socket的连接请求。所谓服 务器端连接,是指当服务器端Socket接收到客户端Socket的连接请求后,就把服务器端Socket的描述 发给客户端,一旦客户端确认了此描述,连接就建立了。在本文中的聊天程序用的就是监听连接, 即服务器设置连接个数后进行监听,客户端进行对服务器端的连接,这样就可以进行相互通信了。 二.TServerSocket和TClientSocket控件的属性 1.ServerSocket的控件属性 threadcachsize:创建服务器线程的最在数目。 port:确定服务器的监视端口。 service:客户通过此属性来识别服务器端口。 2.ClientSocket的控件属性 Socket:此属性参数是应用程序之间通信的端点。 Address:此属性参数为字符串类型,客户端确定服务器端的IP地址。 Host:服务器端的主机名称。 Post:服务器端的监视端口。 Servce:用来识别服务器端口。 Active:确定Socket是否可用(true表示可用)。 ClientType:指定客户机采用哪一种方式(异步/同步)来通信。 三.ServerSocket和ClientSocket控件的事件 1.ServerSocket的事件 onclientconnect:客户与服务器连接且服务器接收申请后,产生此事件。 onclientdisconnect:当和服务器连接的某一个客户机关闭连接后产生此事件。 onGetSocket:一个服务器可以接收多个客户Socket的连接申请。 onGetThread:当ClientType属性值设为StrThreadBlocking时,服务器会产生一个单独的线程来与客户的连接。 onAccept:服务器接收客户的连接申请后,产生此事件。 onClientRead:客户机发送数据到服务器时产生的事件。 2.ClentSocket事件 onConnect:当客户端与服务器端连接上后,产生此事件。 onConnecing:当客户端与服务器端进行连接操作时,产生此事件。 onDisconnect:当客户端关闭操作后产生此事件。 onError:在客户与服务器在建立和通信过程中,如果产生错误时,产生此事件。 onLookup:当客户在计算机网络中寻找服务器时,产生此事件。 onRead:数据到达时产生此事件。
四.ServerSocket和ClientSocket的方法
1.Open方法 此方法适用于ServerSocket和CilentSocket进行建立连接,原型如下: void-Fastcall open(void); 2.Close方法 此方法适用于ServerSocket和CilentSocket进行关闭连接,原型如下: void-Fastcall close(void); 五.编写聊天程序 打开C++Builder 5.0新建一个工程,新建一个Form1窗体,在Form1窗体中添加以下控件: ClientSocket控件: 1个 ServerSocket控件: 1 个 Button控件: 4个 Label控件: 2个 Memo控件: 1个 Edit控件: 2个 TreeView控件: 1个 StatusBar控件: 1个 添加控件 各控件属设置如下: Form1窗体:Caption= "网络聊天器 ". ServerSocket: Name=ServerSocket1;port=10000;ServerType=stNonBlocking;ThreadCacheSize=10. ClientSocket: Name=ClientSocket1;port=10000;ClientType=stNonBlocking. Mome:Name=Mome1;ScrollBars=ssVertical. TreeView:Name=TreeView1; Button: 第一个:Name=Btnlisten;Caption= "监听 "; 第二个:Name=Btnconnect;Caption= "连接 "; 第三个:Name=Btndisconnect;Caption= "断开 "; 第一个:Name=BtnExit;Caption= "退出 "; Label: 第一个:Name=Label1;Caption= "发送 "; 第二个: Name=Label2;Caption= "在线客户 ". Edit: 第一个:Name=Edit1; 第二个: Name=Edit2; StatusBar:Name=StatusBar1; 设置好以上属性值,就可以进行代码的编写了,源程序代码如下: //-------------------------- // "Unit1.h "的源程序 //------------------- #ifndef Unit1H #define Unit1H //-------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <ScktComp.hpp> #include <ExtCtrls.hpp> #include <ComCtrls.hpp> #include <Menus.hpp> #include <ToolWin.hpp> //--------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TClientSocket *ClientSocket1; TServerSocket *ServerSocket1; TMemo *Memo1; TStatusBar *StatusBar1; TEdit *Edit1; TLabel *Label1; TTreeView *TreeView1; TLabel *Label2; TEdit *Edit2; TButton *Btnlisten; TButton *Btnconnect; TButton *Btndisconnect; TButton *BtnExit; void __fastcall FormCreate(TObject *Sender); void __fastcall ClientSocket1Connect(TObject *Sender, TCustomWinSocket *Socket); void __fastcall ServerSocket1Accept(TObject *Sender, TCustomWinSocket *Socket); void __fastcall ServerSocket1ClientDisconnect(TObject *Sender, TCustomWinSocket *Socket); void __fastcall ClientSocket1Disconnect(TObject *Sender, TCustomWinSocket *Socket); void __fastcall ClientSocket1Error(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode); void __fastcall ClientSocket1Read(TObject *Sender, TCustomWinSocket *Socket); void __fastcall ServerSocket1ClientRead(TObject *Sender, TCustomWinSocket *Socket); void __fastcall Edit1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift); void __fastcall ClientSocket1Lookup(TObject *Sender, TCustomWinSocket *Socket); void __fastcall TreeView1Change(TObject *Sender, TTreeNode *Node); void __fastcall BtnlistenClick(TObject *Sender); void __fastcall BtnconnectClick(TObject *Sender); void __fastcall BtndisconnectClick(TObject *Sender); void __fastcall BtnExitClick(TObject *Sender); private: bool IsServer; String Server; // User declarations public: // User declarations __fastcall TForm1(TComponent* Owner); }; //------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //------------------------------------------------------------------------- #endif // "Unit1.cpp "源程序 //----------------------------------------------- #include <vcl.h> #include <stdio.h> #pragma hdrstop #include "Unit1.h " //-------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm " TForm1 *Form1; //-------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { IsServer=false; Server= " "; } //-------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { Btndisconnect-> Enabled=false; } //------------------------------------------------------------------------ //当用户提出连接请求后,客户端会触发OnCreate事件 void __fastcall TForm1::ClientSocket1Connect(TObject *Sender, TCustomWinSocket *Socket) { StatusBar1-> SimpleText= "连接到: "+Server; TreeView1-> Items-> Add(TreeView1-> Selected ,Server); Memo1-> Lines-> Clear(); //定义mouse的类型 Form1-> Cursor=crDefault ; Edit1-> Cursor=crDefault; Memo1-> Cursor=crDefault; //产生一个新的监听 } //------------------------------------------------------------------------- //在服务器接受了客户的请求后会触发OnAccept事件 void __fastcall TForm1::ServerSocket1Accept(TObject *Sender, TCustomWinSocket *Socket) { Memo1-> Lines-> Clear(); IsServer=true; StatusBar1-> SimpleText= "连接到: "+Socket-> LocalHost; TreeView1-> Items-> Add(TreeView1-> Selected ,Socket-> LocalHost); } //------------------------------------------------------------------------- //断开后继续监听 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::ClientSocket1Error(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode) { ShowMessage( "错误!!! 无法连接到服务器 "); ErrorCode=0; Btnlisten-> Enabled=true; Btnconnect-> Enabled=true; Btndisconnect-> Enabled=false; StatusBar1-> SimpleText= " "; //定义mouse的类型 Form1-> Cursor=crDefault ; Edit1-> Cursor=crDefault; Memo1-> Cursor=crDefault; Form1-> Caption = "网络聊天器 "; } //------------------------------------------------------------------------- //客户端接收数据 void __fastcall TForm1::ClientSocket1Read(TObject *Sender, TCustomWinSocket *Socket) { Memo1-> Lines-> Add(Socket-> ReceiveText()); } //--------------------------------------------------------------------------- //服务器端接收数据 void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender, TCustomWinSocket *Socket) { Memo1-> Lines-> Add(Socket-> ReceiveText()); } //------------------------------------------------------------------------- //在建立连接后,双方就可以在Edit1中输入谈话内容开始进 //行交谈了,按下Enter键后,将所在行的文本发送出去 void __fastcall TForm1::Edit1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { AnsiString Data; if(Key==VK_RETURN) {if (Edit2-> Text!= " ") //在没有选择发送的主机名时不能进行发送操作 {if(IsServer) //服务器端发出的数据 {Data= "[ "+TimeToStr(Now())+ "]:( "+ServerSocket1-> Socket-> LocalHost+ ")对 "+ "( "+Edit2-> Text+ ") "+ "说: "+Edit1-> Text; ServerSocket1-> Socket-> Connections[TreeView1-> Selected-> Index]-> SendText(Data); Memo1-> Lines-> Add(Data); Edit1-> Text= " ";} else //客户端发出的数据 { Data= "[ "+TimeToStr(Now())+ "]:( "+ClientSocket1-> Socket-> LocalHost+ ")对 "+ "( "+Edit2-> Text + ") "+ "说: "+Edit1-> Text; ClientSocket1-> Socket-> SendText(Data); Memo1-> Lines-> Add(Data); Edit1-> Text= " ";} } else ShowMessage( "错误!!! 没有选择发送的主机名 "); } } //--------------------------------------------------------------------------- //在网络中搜索服务器端时产生的事件 void __fastcall TForm1::ClientSocket1Lookup(TObject *Sender, TCustomWinSocket *Socket) { //定义mouse的类型 Form1-> Cursor=crHourGlass ; Edit1-> Cursor=crHourGlass; Memo1-> Cursor=crHourGlass; } //选择发向数据的主机名 void __fastcall TForm1::TreeView1Change(TObject *Sender, TTreeNode *Node) { Edit2-> Text=TreeView1-> Selected-> TreeView-> Selected-> Text; StatusBar1-> SimpleText= "连接到: "+TreeView1-> Selected-> TreeView-> Selected-> Text; } //监听 void __fastcall TForm1::BtnlistenClick(TObject *Sender) { ClientSocket1-> Active=false; ServerSocket1-> Active=true; StatusBar1-> SimpleText= "正在监听... "; Form1-> Caption =Form1-> Caption+ "--服务器端 "; 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; Form1-> Caption =Form1-> Caption+ "--客户端 ";} } } //断开 void __fastcall TForm1::BtndisconnectClick(TObject *Sender) { //按下断开 ClientSocket1-> Close(); } //--------------------------------------------------------------------------- //退出 void __fastcall TForm1::BtnExitClick(TObject *Sender) { ClientSocket1-> Close(); ServerSocket1-> Close(); Form1-> Close(); } |
认识C++Builder中的WinSock控件及其相关类
最新推荐文章于 2022-03-02 21:08:29 发布