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 + -
显示快捷键?