chatserveru.cpp

来自「关于书籍《Borland c++Builder工程实践》的源代码」· C++ 代码 · 共 343 行

CPP
343
字号
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "chatserveru.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TChatServerForm *ChatServerForm;
//---------------------------------------------------------------------------
__fastcall TChatServerForm::TChatServerForm(TComponent* Owner)
	: TForm(Owner)
{
  CurrentServerStatus = SS_NOT_RUNNING;
  MainServerSocket->Port = CHAT_SERVER_PORT;
}
//---------------------------------------------------------------------------
void EntryTypeToText(LogEntryType let, AnsiString &text)
{
  switch(let)
  {
    case LET_WARNING:
    {
      text = "提示";
      break;
    }
    case LET_ERROR:
    {
      text = "错误";
      break;
    }
    case LET_SIGNON:
    {
      text = "登录";
      break;
    }
    case LET_SIGNOFF:
    {
      text = "注销";
      break;
    }
    default:
    {
      text = "未知";
      break;
    }
  }
}
//---------------------------------------------------------------------------
void TChatServerForm::AddLogEntry(LogEntryType let, AnsiString EntryText)
{
  TListItem *item = LogEntryListView->Items->Add();

  AnsiString entrytype;
  EntryTypeToText(let, entrytype);
  item->Caption = entrytype;
  item->SubItems->Add(EntryText);
  item->SubItems->Add(TDateTime::CurrentDateTime());
}
//---------------------------------------------------------------------------
void TChatServerForm::SetServerStatus(ServerStatus _serverstatus)
{
   CurrentServerStatus = _serverstatus;
}
//---------------------------------------------------------------------------
void __fastcall TChatServerForm::StartStopServerClick(TObject *Sender)
{
  switch(CurrentServerStatus)
  {
    case SS_NOT_RUNNING:
    {
      MainServerSocket->Open();
      SetServerStatus(SS_RUNNING);
      AddLogEntry(LET_WARNING, "服务器已启动");
      StartStopServer->Caption = "停止";
      break;
    }
    case SS_RUNNING:
    {
      MainServerSocket->Close();
      SetServerStatus(SS_NOT_RUNNING);
      AddLogEntry(LET_WARNING, "服务器已停止");
      StartStopServer->Caption = "开始";
      break;
    }
  }
  UpdateStatusBar();
}
//---------------------------------------------------------------------------
void TChatServerForm::AddConnectionToListView(TCustomWinSocket *ClientSocket)
{
  //客户第一个要发送的就是他的绰号
  AnsiString UserNickName = "未知";

  TListItem *TempItem = ConnectionsListView->Items->Add();

  TempItem->Caption = UserNickName;
  TDateTime CurrentDT(TDateTime::CurrentDateTime());
  TempItem->SubItems->Add(ClientSocket->RemoteHost);
  TempItem->SubItems->Add(CurrentDT);
  TempItem->Data = ClientSocket;
}
//---------------------------------------------------------------------------
TListItem * TChatServerForm::ListItemBySocket(TCustomWinSocket *Socket)
{
  for (int i = 0; i <	ConnectionsListView->Items->Count; i++)
  {
    if (reinterpret_cast<TCustomWinSocket *>(ConnectionsListView->Items->Item[i]->Data) == Socket)
    {
      return ConnectionsListView->Items->Item[i];
    }
  }
  return NULL;
}
//---------------------------------------------------------------------------
void TChatServerForm::RemoveConnectionFromListView(TCustomWinSocket *Socket)
{
  TListItem *item = ListItemBySocket(Socket);
  if (item)
    ConnectionsListView->Items->Delete(item->Index);
}
//---------------------------------------------------------------------------
void TChatServerForm::SetUserBySocket(TCustomWinSocket *Socket, const AnsiString &UserNickName)
{
  TListItem *item = ListItemBySocket(Socket);
  if (item)
    item->Caption = UserNickName;
}
//---------------------------------------------------------------------------
void TChatServerForm::GetUserBySocket(TCustomWinSocket *Socket, AnsiString &UserNickName)
{
  TListItem *item = ListItemBySocket(Socket);
  if (item)
    UserNickName = item->Caption;
  else
    UserNickName = "未知";
}
//---------------------------------------------------------------------------
int TChatServerForm::GetSocketNoByUser(AnsiString User)
{
   //由用户名得到其对应Socket号
   AnsiString  usergot;
   for (int i = 0; i < MainServerSocket->Socket->ActiveConnections; i++)
   {
      GetUserBySocket(MainServerSocket->Socket->Connections[i],usergot);
      if (usergot==User)
         return i;
   }
   return -1;
}
//---------------------------------------------------------------------------
void TChatServerForm::UpdateStatusBar(bool DecUse/* = false*/)
{
  switch(CurrentServerStatus)
  {
    case SS_NOT_RUNNING:
    {
      ChatServerStatusBar->SimpleText = "选择开始菜单进入聊天";
      break;
    }
    case SS_RUNNING:
    {
      if (DecUse)
        ChatServerStatusBar->SimpleText = IntToStr(MainServerSocket->Socket->ActiveConnections - 1) + "个客户已连接";
      else
        ChatServerStatusBar->SimpleText = IntToStr(MainServerSocket->Socket->ActiveConnections) + "个客户已连接";
      break;
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TChatServerForm::MainServerSocketClientConnect(TObject *Sender,
	  TCustomWinSocket *Socket)
{
  Socket->Data = 0;
  AddConnectionToListView(Socket);
  UpdateStatusBar();
}
//---------------------------------------------------------------------------
void TChatServerForm::SendNotification(ServerNotification sn, AnsiString additional, TCustomWinSocket *ExcludeSocket)
{
  AnsiString UserNickName;
  GetUserBySocket(ExcludeSocket, UserNickName);
  switch(sn)
  {
    case SN_LOGON:
    {
      BroadcastMessage(UserNickName + " 刚登录", ExcludeSocket);
      AddLogEntry(LET_SIGNON, UserNickName);
      break;
    }
    case SN_LOGOFF:
    {
      BroadcastMessage(UserNickName + " 刚注销", ExcludeSocket);
      AddLogEntry(LET_SIGNOFF, UserNickName);
      break;
    }
    case SN_PUBLIC_MSG:
    {
      AnsiString msgtosend = "<" + UserNickName + "> " + additional;
      BroadcastMessage(msgtosend, ExcludeSocket);
      break;
    }
    case SN_PRIVATE_MSG:
    {
      AnsiString msgtosend = "<" + UserNickName + "> " + additional;
      MulticastMessage(msgtosend,MuticastUserList);
      break;
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TChatServerForm::MainServerSocketClientDisconnect(TObject *Sender,
	  TCustomWinSocket *Socket)
{
  SendNotification(SN_LOGOFF, "", Socket);
  RemoveConnectionFromListView(Socket);
  UpdateStatusBar(true);
}
//---------------------------------------------------------------------------
void __fastcall TChatServerForm::MainServerSocketClientError(TObject *Sender,
	  TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
  AddLogEntry(LET_ERROR, "套接字错误 " + IntToStr(ErrorCode));
  SendNotification(SN_LOGOFF, "", Socket);
  ErrorCode = 0;
  RemoveConnectionFromListView(Socket);
  UpdateStatusBar(true);
}
//---------------------------------------------------------------------------
void TChatServerForm::BroadcastMessage(AnsiString Message, TCustomWinSocket *ExcludeSocket)
{
  int i;
  if(!Message.AnsiPos("刚登录"))
  {
      for (i = 0; i < MainServerSocket->Socket->ActiveConnections; i++)
          MainServerSocket->Socket->Connections[i]->SendText(Message);
  }
  else
      for (i = 0; i < MainServerSocket->Socket->ActiveConnections; i++)
      {
          if (MainServerSocket->Socket->Connections[i] != ExcludeSocket)
          {
              MainServerSocket->Socket->Connections[i]->SendText(Message);
          }
      }
}
//---------------------------------------------------------------------------
void TChatServerForm::MulticastMessage(AnsiString Message,AnsiString UserList)
{
   int SocketNo,pos;
   AnsiString user,userlist=UserList;

   while (userlist.Pos("*"))
   {
      pos=userlist.Pos("/");
      if(pos)  //非最后一个用户
      {
          user=userlist.SubString(1,pos-1);
          SocketNo=GetSocketNoByUser(user);
          if(SocketNo>-1)
             MainServerSocket->Socket->Connections[SocketNo]->SendText(Message);
          else
             ShowMessage("Socket not found!");
          userlist=userlist.SubString(pos+1,userlist.Length()-pos);
      }
      else    //最后一个用户
      {
          user=userlist.SubString(1,userlist.Length()-1);
          SocketNo=GetSocketNoByUser(user);
          if(SocketNo>-1)
             MainServerSocket->Socket->Connections[SocketNo]->SendText(Message);
          else
             ShowMessage("Socket not found!");
          userlist="";
      }
   }
}
//---------------------------------------------------------------------------
void __fastcall TChatServerForm::MainServerSocketClientRead(TObject *Sender,
	  TCustomWinSocket *Socket)
{
  AnsiString UserNickName, UserLogin;
  int pos1,pos2;
  if (!Socket->Data)
  {
    UserNickName = Socket->ReceiveText();
    int index = UserNickName.Pos("\n");
    if (index > 1)
      UserNickName.SetLength(index-1);
    else
      UserNickName = "未知或无效" + IntToStr(Socket->SocketHandle);
    SetUserBySocket(Socket, UserNickName);
    Socket->Data = (void *)1;
    //添加用户序列:格式: xxx,欢迎登录服务器/user1/user2/.../usern*
    AnsiString loginresponse = UserNickName + ", 欢迎登录到服务器";
    for (int i = 0; i < MainServerSocket->Socket->ActiveConnections; i++)
    {
       GetUserBySocket(MainServerSocket->Socket->Connections[i],UserLogin);
       if (UserLogin!= UserNickName)
       {
          loginresponse+="/";
          loginresponse+=UserLogin;
          //MainServerSocket->Socket->Connections[i]->SendText(Message);
       }
    }
    loginresponse+="*";

    Socket->SendText(loginresponse);
    SendNotification(SN_LOGON, "", Socket);
  }
  else //转发信息!
  {
    AnsiString recvtxt = Socket->ReceiveText(),sendtxt;
    if(recvtxt.AnsiPos("Multicast")) //多播信息
    {
       //多播格式:  Multicast$user1/user2/.../usern*信息正文
       pos1=recvtxt.Pos("$");
       pos2=recvtxt.Pos("*");
       //提取用户序列 格式:user1/user2/.../usern*
       MuticastUserList=recvtxt.SubString(pos1+1,pos2-pos1);
       //提取信息正文
       sendtxt=recvtxt.SubString(pos2+1,recvtxt.Length()-pos2);
       //发送信息正文
       SendNotification(SN_PRIVATE_MSG, sendtxt,Socket);
    }
    else   //广播
       SendNotification(SN_PUBLIC_MSG, recvtxt , Socket);
  }
}
//---------------------------------------------------------------------------
void __fastcall TChatServerForm::ExitClick(TObject *Sender)
{
  Close();
}
//---------------------------------------------------------------------------
void __fastcall TChatServerForm::ClearLogClick(TObject *Sender)
{
    LogEntryListView->Items->Clear();
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?