分享
 
 
 

BCB 高手进阶 (八)TServerSocket和TClientSocket应用技巧

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

BCB 高手进阶

(八)TServerSocket和TClientSocket应用技巧

:nxyc_twz@163.com

在网络编程中,WinSocket API编程是最基本,也是最繁锁的部分。但是,如果你是采用C++Builder 5 作为编程平台,事情就变得简单的多了!通过我的介绍,相信你一定能快速掌握设计基于C/S体系的方法与技巧。

在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 要连接的主机名,如www.cpcw.com

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 说明

TCheckBox 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->ActiveConnections;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->ActiveConnections;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->ActiveConnections;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);

我们的闲聊程序完成了,在局域网中试试吧?如果你只有一台机器,客户程序在连接时服务器时输入localhost或你机器的名字就可以了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有