TServerSocket和TClientSocket的使用
关键字:TServerSocket,TClientSocket
作者:佚名更新:2003-3-9 浏览:18820
在网络编程中,WinSocket API编程是最基本,也是最麻烦的地方(说句不怕影响形象的话,我对此就是一知半解)。但是,如果你是使用C++Builder作为编程平台,你就偷着乐吧,有了BCB,菜鸟变高手!:-)
在BCB中,TServerSocket和TClientSocket涵盖了基本的WinSocket编程,其中TServerSocket 作为服务器方使用,TClientSocket作为客户端使用,这两个组件本身并不提供Socket连接,但是他们都有一个Socket属性,这个属性才提供了Socket连接。下面就先向大家介绍一下这两个组件常用的方法属性,然后在通过一个例子来看看这两个组件的使用。
1)TServerSocket
名称类型说明
Socket TServerWinSocket 最重要的属性,提供Socket连接,事实上发送/接收数据都要靠这个属性.
Port int 要监听的端口,如果在Service属性中指定了服务类型,此属性将被忽略. Service AnsiString 提供的服务,如HTTP、FTP等,如果在这里指定了服务类型,
Port将被忽略,因为各种服务都有特定的端口,如FTP:21、HTTP:80 ServerType TServerType 设置与客户连接的方式,取值为两个枚举常量stNonBlocking和 stThreadBlocking,stNonBlocking表示用非阻塞方式连接每一个客户
每个连接都在一个单独的线程中处理。并用OnClientRead()和
OnClientWrite()通知服务器端的Socker进行读写。stThreadBlocking
表示以阻塞方式连接客户,即以主动查询的方式可客户连接。
Active bool 激活服务,相当于调用Open()方法。
OnAccept事件当有客户请求连接时触发
OnClientRead事件通知服务器去读取有关信息。OnClientWrite与此类似。
2)TClientSocket
名称类型说明
Socket TClientWinSocket 同TServerSocket
Active bool 同TServerSocket
Address AnsiString 服务器的IP地址,如202.98.35.14
ClientType TClientType 与服务器连接方式,取值为两个枚举常量ctNonBlocking,tBlocking。
ctNonBlocking表示非阻塞方式,ctBlocking表示阻塞方式,详见上例。Host AnsiString 要连接的主机名,如https://www.wendangku.net/doc/5617875613.html,
Port int 同TServerSocket
Service AnsiString 同TServerSocket
OnConnect事件当连接时发生,OnConnecting、OnDisConnect与此类似
OnRead事件通知客户机去读取有关信息。OnWrite与此类似。
TServerSocket和TClientSocket只提供基本的服务器/客户机的连接,真正提供数据传输的是它们都有的属性Socket,它的类型分别是TServerWinSocket和TClientWinSocket,而TServerWinSocket和TClientWinSocket的父类都是TCustomWinSocket,下面我们就来看看TServerWinSocket和TClientWinSocket常用的属性和方法。
共同的属性方法(来源于TCustomWinSocket)
名称类型说明
Connected bool 检查是否连接成功
LocalAddress AnsiString 本地IP地址,与此类似LocalHost:本机域名,LocalPort:本机端口
RemoteAddress AnsiString 另一端的IP地址,与此类似RemoteHost:另一端域名,
RemotePort:另一端端口
SocketHandle int 只读,返回Socket对象的Windows句柄,调用WinSocket API函数会用到它。
Handle HWND Socket能够接受到的异步事件都是以Windows消息的形式发送给此句柄的。
Close()方法作为服务器,关闭所有连接;作为客户机,关闭自己与服务器的连接
SendText(AnsiString)方法发送一个字符串,
SendBuf(void* buff,int count)发送缓冲区buff中的count个字节,返回实际发送的字节数SendStream(TStream* AStream)发送一个流到Socket中。
ReceiveText()从Socket中读取并返回一个字符串。
ReceiveLength()从Socket读取数据需多少字节的缓冲区。
ReceiveBuf(void* buff,int count)从Socket中读取count字节的数据到buff。
TClientWinSocket
TClientWinSocket只增加了一个ClientType属性,
用于决定与服务器的连接类型(参见TClientSocket->ClientType)。
TServerWinSocket
名称类型说明
ServerType 服务类型,参见TServerSocket->ServerType。
ActiveConnection int只读,返回当前活动的连接数。
Connection TCustomWinSocket数组,索引n表示第n+1个连接,如Connection[0]表示第一个连接。
有了这些知识,我们就可以完成一些基本的WinSocket编程了,下面就结合一个简单的闲聊程序来看看具体的应用。
首先在窗体上放置以下VCL组件,并修改相应属性:
类型 Name 属性 Caption/Text 说明
本文转自研究w w w m&m w
CheckBox ckListen 监听当选取时,本程序作为服务器
TCheckBox ckConnect 连接当选取时,本程序作为客户机
TEdit edName 无名氏闲聊时所用的名字。
TBitBtn bbtSave&S 保存单击时保存谈话内容
TBitBtn bbtClose&C 关闭单击时关闭此窗口(设置Kind=bkClose)
TEdit edTalk 在此输入谈话内容
TMemo mmTalk 在此显示谈话内容
TServerSocket ServerSocket1作服务器时使用(设置Port=2222)
TClientSocket ClientSocket1作为客户时使用(设置Port=2222)
TSaveDialog sdTalk保存文件时的选项(设置DefaultExt="*.txt",Filter=文本文件(*.TXT)
|*.txt|所有文件(*.*)|*.*)。
TStatusBar StatusBar1 用于显示一些提示信息,只要在属性"Pannels"中加一栏即可
程序作为服务器的设置:
当单击"监听"时,如果没有监听则开始监听,在提示栏中显示"监听",并把"连接"这个复选框无效。如果已经监听,则取消监听,并使"连接"这个复选框有效。所以,在ckListen的OnClick事件中加入以下代码:
if(ServerSocket1->Active)
{
ServerSocket1->Active=false;
ckListen->Checked=false;
StatusBar1->Panels->Items[0]->Text="";
}
else
{
ServerSocket1->Active=true;
ckListen->Checked=true;
ClientSocket1->Active=false;
StatusBar1->Panels->Items[0]->Text="监听..." ;
}
ckConnect->Enabled=!(ckListen->Checked);
当有客户加入时,向所有的客户发出通知:并在自已的mmTalk加入此消息:所以在ServerSocket1的OnAccept事件中加入如下代码:
int i;
AnsiString str1="服务器消息:"+Socket->RemoteHost+"加入";
for(i=0;i
ServerSocket1->Socket->Connections[i]->SendText("服务器消息:"+Socket->RemoteHost+"加入");
StatusBar1->Panels->Items[0]->Text=str1;
mmTalk->Lines->Add(str1);
当客户机通知服务器读信息时,首先读出字符串,然后把读到的字符串发送到每一台连接的客户,并在自已的mmTalk中加入客户发送来的字符串。所以,在TServerSocket的OnClientRead事件中加入以下代码:
AnsiString str1=Socket->ReceiveText();
mmTalk->Lines->Add(str1);
int i;
for(i=0;i
ServerSocket1->Socket->Connections[i]->SendText(str1);
程序作为客户机的设置:
当单击"连接"时,如果还未连接,则询问要连接的主机,然后连接之,屏蔽"监听";如果已经连接,则断开连接。"监听"使能。所以,在ckConnect的OnClick事件中加入以下代码:
if(ClientSocket1->Active)
{
ClientSocket1->Active=false;
ckConnect->Checked =false;
}
else
{
AnsiString Server="localhost";
if(InputQuery("连接","请输入要连接的主机地址:",Server))
{
ClientSocket1->Host=Server;
ClientSocket1->Active=true;
ckConnect->Checked =true;
}
}
ckListen->Enabled= !(ckConnect->Checked);
当连接服务器成功时,在状态栏中显示此信息,所以,在ClientSocket1的
ClientSocket1Connect中加入:
StatusBar1->Panels->Items[0]->Text ="连接到主机:"+Socket->RemoteHost;
当服务器发送字符串来时,把它加入mmTalk中,但如果本字符串就是自已发送的(因为服务器会把收到的消息发给每一客户),为条信息就是重复的,所以,要比较mmTalk中最后两条信息是否相同,如果相同,则删除重复信息。代码如下:
mmTalk->Lines->Add(Socket->ReceiveText());
int i=mmTalk->Lines->Count-1;
if(mmTalk->Lines->Strings[i]==mmTalk->Lines->Strings[i-1])
mmTalk->Lines->Delete(i);
公用部分
当在edTalk输入交谈内容,按回车键表示输入完成,此时把交谈内容发送出去并清除edTalk 的内容。在发送信息时,要看本程序是作为服务器还是客户机,如果是服务器则把信息发送到每一个客户;如果是作为客户则把信息发送到服务器。代码如下:
if(Key==13)
{
mmTalk->Lines->Add(edName->Text+":"+edTalk->Text);
if(ckListen->Enabled&&ckConnect->Enabled==false)
//"监听"有效,"连接"无效。表示是服务器
{
int i;
for(i=0;i
ServerSocket1->Socket->Connections[i]->SendText(edName->Text+":"+edTalk->Text);
}
else
{
ClientSocket1->Socket->SendText(edName->Text+":"+edTalk->Text);
}
edTalk->Text="";
}
mmTalk的内容不可能永远增加,所以当它有100行时就清空它,在mmTalk的OnChange 事件中检查:
if(mmTalk->Lines->Count>=100)mmTalk->Lines->Clear();
当然你也可以双击mmTalk来清空它,在mmTalk的OnDblClick事件中加入:
mmTalk->Lines->Clear();
当你觉得谈话的内容很有意思,你可以单击bbtSave打开保存对话框设置保存特性,所以在bbtSave的onClick中加入代码:
if(sdTalk->Execute())
mmTalk->Lines->SaveToFile(sdTalk->FileName);
OK,我们的闲聊程序就完成了,在局域网中试试吧?如果你只有一台机器,客户程序在连接时服务器时输入localhost或你机器的名字就可以了。
熟悉了这两个组件我们就可以写如联众游戏一样的网络游戏了(至少理论上如此),我也正想写一个网上赌博程序去诈骗我的同事,千万不要告诉他们哦!:=)
ServerSocket和ClientSocket控件事件
2012-05-09 13:49 达内培训
本文继认识C++Builder中的WinSock控件及其相关类、TServerSocket和TClientSocket控件的属性后将向你展示ServerSocket和ClientSocket控件的事件,希望能对你有所帮助。
1.ServerSocket的事件
onclientconnect:客户与服务器连接且服务器接收申请后,产生此事件。onclientdisconnect:当和服务器连接的某一个客户机关闭连接后产生此事件。
onGetSocket:一个服务器可以接收多个客户Socket的连接申请。
onGetThread:当ClientType属性值设为StrThreadBlocking时,服务器会产生一个单独的线程来与客户的连接。
onAccept:服务器接收客户的连接申请后,产生此事件。
onClientRead:客户机发送数据到服务器时产生的事件。
2.ClentSocket事件
onConnect:当客户端与服务器端连接上后,产生此事件。
onConnecing:当客户端与服务器端进行连接操作时,产生此事件。
onDisconnect:当客户端关闭操作后产生此事件。
onError:在客户与服务器在建立和通信过程中,如果产生错误时,产生此事件。
onLookup:当客户在计算机网络中寻找服务器时,产生此事件。
onRead:数据到达时产生此事件。
完整的学习才能让你进步更快!
TServerSocket和TClientSocket控件
2012-05-09 13:49 达内
本文是用WinSock控件编写网络聊天器的第二部分知识内容,希望你能认真参悟。
以下为正文:
1.ServerSocket的控件属性
threadcachsize:创建服务器线程的最在数目。
port:确定服务器的监视端口。
service:客户通过此属性来识别服务器端口。
2.ClientSocket的控件属性
Socket:此属性参数是应用程序之间通信的端点。
Address:此属性参数为字符串类型,客户端确定服务器端的IP地址。
Host:服务器端的主机名称。
Post:服务器端的监视端口。
Servce:用来识别服务器端口。
Active:确定Socket是否可用(true表示可用)。
ClientType:指定客户机采用哪一种方式(异步/同步)来通信。
编写聊天程序
2012-05-09 13:40 达内
关注本站的朋友一定了解,本文是用WinSock控件编写网络聊天器的最后部分,希望本文能对你有帮助。另外达内的老师希望你能将它付出实践,那将让你收获更大!
打开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
#include
#include
#include
#include
#include
#include
#include
#include
//---------------------------------------------------------------------
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
#include
#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();
}