基于C++ Builder 5的Socket组件实现的聊天程序(三)

本文档详细介绍了如何使用C++ Builder 5的TClientSocket组件创建一个聊天客户端程序,包括创建主窗体、设置组件属性、编写相关代码,实现了连接、接收、发送等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                   基于C++ Builder 5的Socket组件实现的聊天程序(三) 

 2.创建客户端程序

1)创建主窗体

选择“File | New Application”菜单命令创建一个新工程,该工程包括一个空白窗体,将窗体的“Name”属性改为“MainForm”,选择“File | Save Project As…”菜单命令,把Unit1.cpp保存为 ChatClientMain.cpp Project1.bpr 保存为 ChatClient.bpr

剩下的和服务器的窗体创建方法差不多,我就不啰嗦了,我再把客户端的界面贴一下,大家应该都能理解。

别忘了,这次是TClientSocket组件而不是TServerSocket ,其他的组件都差不多。

 

                           

 

窗体和组件的属性设置如下表:

 

组件

属性

属性值

Form1

FormStyle

fsNormal

Name

MainForm

Caption

客户端

Label1

Caption

聊天内容

Label2

Caption

发送信息

Label3

Caption

在线用户

Button1

Caption

发送

Name

SendButton

不是BtnToPer了,其实没有影响,名字无所谓

Button2

Caption

所有人

Name

BtnToAll

Edit1

Name

EdtSend

ListBox1

Name

ListUserBox

Memo1

Name

ChatMemo

ClientSocket1

Port

8999

ServerType

stNonBlocking

MenuItem1

Name

MenuConnect

Caption

登陆

MenuItem2

Name

MenuDisConnect

Caption

离开

MenuItem3

Name

MenuHelp

Caption

帮助

MenuItem4

Name

MenuAbout

Caption

关于

 

    也许大家会问我的客户端的界面图片里只有“登陆”、“帮助”和“关于”三个菜单项啊,没有“离开”啊,等你登陆成功后就有“离开”了。

 

2)设计代码

 

ChatClientMain.h头文件的代码如下:

//---------------------------------------------------------------------------

#ifndef ChatClientMainH

#define ChatClientMainH

//---------------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <Menus.hpp>

#include <ScktComp.hpp>

#include <ComCtrls.hpp>

//---------------------------------------------------------------------------

class TMainForm : public TForm

{

__published:   // IDE-managed Components

        TMemo *ChatMemo;

        TListBox *ListUserBox;

        TLabel *Label1;

        TLabel *Label2;

        TLabel *Label3;

        TEdit *EdtSend;

        TButton *SendButton;

        TMainMenu *MainMenu1;

        TClientSocket *ClientSocket1;

        TMenuItem *MenuConnect;

        TMenuItem *MenuDisConnect;

        TStatusBar *StatusBar1;

        TButton *BtnToAll;

        TMenuItem *MenuHelp;

        TMenuItem *MenuAbout;

 

    // 同样,上面的代码是设计好窗体后自动生成的

    // 下面的这些函数也应该不难理解

        void __fastcall MenuConnectClick(TObject *Sender);

        void __fastcall ClientSocket1Connect(TObject *Sender,

                    TCustomWinSocket *Socket);

        void __fastcall ClientSocket1Read(TObject *Sender,

          TCustomWinSocket *Socket);

        void __fastcall ClientSocket1Error(TObject *Sender,

          TCustomWinSocket *Socket, TErrorEvent ErrorEvent,

          int &ErrorCode);

        void __fastcall ListUserBoxClick(TObject *Sender);

        void __fastcall BtnToAllClick(TObject *Sender);

        void __fastcall SendButtonClick(TObject *Sender);

        void __fastcall MenuSetClick(TObject *Sender);

        void __fastcall MenuDisConnectClick(TObject *Sender);

        void __fastcall ClientSocket1Disconnect(TObject *Sender,

          TCustomWinSocket *Socket);

        void __fastcall MenuHelpClick(TObject *Sender);

        void __fastcall MenuAboutClick(TObject *Sender);

private:    // User declarations

 

        BOOL m_HasConnected;

        AnsiString m_sHostAddress;

        AnsiString m_sName;

        AnsiString m_sIsChat;

        AnsiString m_sSpeakTo;

        AnsiString m_sPartTo;

        AnsiString m_sPartFr;

        AnsiString m_sSendInfo;

        AnsiString m_sIsName;

       

public:            // User declarations

        __fastcall TMainForm(TComponent* Owner);

};

//---------------------------------------------------------------------------

extern PACKAGE TMainForm *MainForm;

//---------------------------------------------------------------------------

#endif

 

 

源文件ChatClientMain.cpp的代码如下:

 

//---------------------------------------------------------------------------

 

#include <vcl.h>

#pragma hdrstop

 

#include "ChatClientMain.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TMainForm *MainForm;

//---------------------------------------------------------------------------

__fastcall TMainForm::TMainForm(TComponent* Owner)

        : TForm(Owner)

{

    m_sHostAddress = "192.168.0.187";  // 服务端程序所在的机器的IP地址,这是我

// IP地址,其实IP地址设在这里不太人性

// 化,应该在客户端程序的界面层对服务器的// IP地址进行自由设置,这样当服务端程序放// 在别的机器上的时候就不用来这里改代码

// 了,大家可以自己实现一下,很简单的,弄// 一个文本框,让m_sHostAddress = 文本框

//  ->Text 就行了

    ClientSocket1->Active = false;

    ClientSocket1->Address = m_sHostAddress;

    ClientSocket1->Port = 8999;     // 端口好也最好弄成上面IP地址那样的实现方法

    m_sSpeakTo = "ALL";

    m_sIsName = "NA";

    m_sIsChat = "CT";

    m_sPartTo = "#";

    m_sPartFr = "$";

    m_HasConnected = false;

    TDateTime NowTime;

    NowTime = Now();

    StatusBar1->SimpleText = NowTime.DateTimeString();

}

//---------------------------------------------------------------------------

void __fastcall TMainForm::MenuConnectClick(TObject *Sender)

{

    InputQuery("请输入用户名","(不能包含#$字符)  ",m_sName);

    while(m_sName.IsEmpty())

    {

        MessageBox(NULL,"用户名不能为空","",MB_OK);

        InputQuery("请输入用户名","(不能包含#$字符)",m_sName);

    }

 

    for (int i=1;i<m_sName.Length()+1;i++)

    {

        if (m_sName.SubString(i,1)=="#")

        {

            MessageBox(NULL,"用户名不合法,请重新输入","",MB_OK);

            InputQuery("请输入用户名","(不能包含#$字符)",m_sName);

        }

        else if(m_sName.SubString(i,1)=="$")

        {

            MessageBox(NULL,"用户名不合法,请重新输入","",MB_OK);

            InputQuery("请输入用户名","用户名:",m_sName);

        }

    }

 

    ClientSocket1->Open();

 

    MenuConnect->Visible = false;

    MenuDisConnect->Visible = true;

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::ClientSocket1Connect(TObject *Sender,

      TCustomWinSocket *Socket)

{

    Socket->SendText(m_sIsName+m_sName);

    AnsiString sTemp;

    sTemp.sprintf("%s登陆成功",m_sName);

    m_HasConnected = true;       

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::ClientSocket1Read(TObject *Sender,

      TCustomWinSocket *Socket)

{

    AnsiString sFr;

    AnsiString sInfo;

    AnsiString sType;

    AnsiString sChat;

    AnsiString sAddr;

    int iPosFr,iPosWel;

    int iIndex;

 

    sInfo = Socket->ReceiveText();

    sType = sInfo.SubString(1,2);

    iPosFr = sInfo.Pos(m_sPartFr);

 

    sFr = sInfo.SubString(3,iPosFr-3);

 

   

    if (sInfo=="CLEAR")

    {

        ListUserBox->Items->Clear();

    }

    else

    {

        if (sType==m_sIsName)

        {

 

            if (sFr!=m_sName)

            {

 

                StatusBar1->SimpleText = sFr+"刚加入";

                ChatMemo->Lines->Add(sFr+"刚加入");

            }

            ListUserBox->Items->Add(sFr);

        }

        else if (sType==m_sIsChat)

        {

            sChat = sFr+sInfo.SubString(iPosFr+1,

                                   sInfo.Length()-iPosFr+1);

            ChatMemo->Lines->Add(sChat);

        }

        else

        {

            ChatMemo->Lines->Add(sInfo);

        }

     }

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::ClientSocket1Error(TObject *Sender,

      TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)

{

    ErrorCode = 0;       

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::ListUserBoxClick(TObject *Sender)

{

    if (m_HasConnected)

    {

        AnsiString sTemp;

        if (m_sName == ListUserBox->Items->Strings[ListUserBox->ItemIndex])

        {

            MessageBox(NULL,"不能与自己交谈","",MB_OK);

        }

        else

        {

            MainForm->Caption = ""+

                  ListUserBox->Items->Strings[ListUserBox->ItemIndex]+"交谈中";

        

            m_sSpeakTo = ListUserBox->Items->Strings[ListUserBox->ItemIndex];

        }

    }

    else

    {

        MessageBox(NULL,"对不起,请先登录","",MB_OK);

    }

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::BtnToAllClick(TObject *Sender)

{

    AnsiString sTemp;

    m_sSpeakTo = "ALL";

    sTemp = m_sIsChat+m_sName+m_sPartFr+m_sSpeakTo+m_sPartTo+EdtSend->Text;

    if(!(ClientSocket1->Active))

    {

        MessageBox(NULL,"请先登陆","",MB_OK);

    }

    else

    {

        if (EdtSend->Text=="")

        {

            MessageBox(NULL,"发送内容不能为空","",MB_OK);

        }

        else

        {

            ClientSocket1->Socket->SendText(sTemp);

            EdtSend->Clear();

            StatusBar1->SimpleText = "发送完毕";

        }

    }

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::SendButtonClick(TObject *Sender)

{

    AnsiString sTemp;

    sTemp = m_sIsChat+m_sName+m_sPartFr+m_sSpeakTo+m_sPartTo+EdtSend->Text;

    if (!(ClientSocket1->Active))

    {

        MessageBox(NULL,"请先登陆","",MB_OK);

    }

    else

    {

        if (EdtSend->Text=="")

        {

            MessageBox(NULL,"发送内容不能为空","",MB_OK);

        }

        else

        {

            if (m_sSpeakTo!="ALL")

            {

                ClientSocket1->Socket->SendText(sTemp);

                ChatMemo->Lines->Add(m_sName+" 说:");

                ChatMemo->Lines->Add(" "+EdtSend->Text);

                EdtSend->Clear();

            }

            StatusBar1->SimpleText = "发送完毕";

        }

    }

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::MenuDisConnectClick(TObject *Sender)

{

    if(ClientSocket1->Socket->Connected)

    {

        ClientSocket1->Socket->Close();

        if (!(ClientSocket1->Active))

        {

            MenuConnect->Visible = true;

            MenuDisConnect->Visible = false;

        }

    }

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::ClientSocket1Disconnect(TObject *Sender,

      TCustomWinSocket *Socket)

{

    ListUserBox->Items->Clear();

    m_HasConnected = false;

    ChatMemo->Clear();

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::MenuHelpClick(TObject *Sender)

{

   MessageBox(NULL,"点“登陆”,输入用户名/r/n点“离开”,断开与服务器的连接",

                                                        "",MB_OK);

}

//---------------------------------------------------------------------------

 

void __fastcall TMainForm::MenuAboutClick(TObject *Sender)

{

    MessageBox(NULL,

    "作者:赵永康/r/n完成日期:2009729/r/n版本:5.0/r/nQQ:516996841",

    "",MB_OK);

           //  MessageBox ,在需要换行的后面加上 "/r/n" 即可

}

//---------------------------------------------------------------------------

 

 

参考着服务端程序,客户端程序很好理解的。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值