📄 gserver.cpp
字号:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "GServer.h"
#include <stdio.h>
#pragma package(smart_init)
#define LineAdd(a,b) Lines->Insert(a,b)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
static inline void ValidCtrCheck(GServer *)
{
new GServer(NULL);
}
//---------------------------------------------------------------------------
__fastcall GServer::GServer(TComponent* Owner)
: TMemo(Owner)
{
sk=INVALID_SOCKET;
maxChaters=0;
bListen=false;
bDoorClose=false;
SRBuffer=NULL;
gsu=NULL;
szTemp=NULL;
tempBuffer=NULL;
id=1000;
CloseRefuse=1;
zeroInt=0xff;
dhSize=sizeof(DataHeader);
}
//---------------------------------------------------------------------------
namespace Gserver
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(GServer)};
RegisterComponents("GControl", classes, 0);
}
}
//---------------------------------------------------------------------------
bool GServer::Listen()
{
if(bListen)DisConnect();
//加入SSYSTEM各个成员变量的检验
Perform(WM_VSCROLL,SB_TOP,0);
sockaddr_in sock;
sock.sin_family=AF_INET;
sock.sin_port=htons(Port);
sock.sin_addr.s_addr=LocalIp();
if(sock.sin_addr.s_addr==INADDR_NONE){LineAdd(0,"获取本机IP失败!无法进入监听模式!");return false;};
maxChaters=20;
tBufferSize=4096;
RBufferSize=2049;
SRBuffer=new char[4097];
gsu=new GServerUnit[maxChaters];
tempBuffer=new char[4097];
szTemp=new char[128];
ZeroMemory(SRBuffer,4097);
ZeroMemory(gsu,sizeof(GServerUnit)*maxChaters);
ZeroMemory(tempBuffer,4097);
ZeroMemory(szTemp,128);
for(int i=0;i<maxChaters;i++)gsu[i].sk=INVALID_SOCKET;
try
{
sk=socket(AF_INET,SOCK_STREAM,0);
if(sk==INVALID_SOCKET)throw 1;
int iRet=bind(sk,(sockaddr*)&sock,sizeof(sockaddr_in));
if(iRet==SOCKET_ERROR)
{
if(WSAGetLastError()==WSAEADDRINUSE)
LineAdd(0,"该端口已经被使用!请使用其它端口!");
else
LineAdd(0,"未知的Winsock错误!");
throw 1;
}
if(listen(sk,5)==SOCKET_ERROR){LineAdd(0,"无法进入监听模式!");throw 1;}
if(WSAAsyncSelect(sk,Handle,WM_CHATSERVER,FD_ACCEPT)==SOCKET_ERROR){LineAdd(0,"异步消息选择失败!");throw 1;}
}
catch(...)
{
if(sk!=INVALID_SOCKET)closesocket(sk);
if(SRBuffer)delete[]SRBuffer;
if(szTemp)delete[]szTemp;
if(gsu)delete[]gsu;
if(tempBuffer)delete[]tempBuffer;
return false;
}
bListen=true;
LineAdd(0,"已经进入监听模式!等待客户连接!");
return true;
}
void GServer::DisConnect()
{
LeaveAll();
if(SRBuffer)delete[]SRBuffer;
if(szTemp)delete[]szTemp;
if(gsu)delete[]gsu;
if(tempBuffer)delete[]tempBuffer;
SRBuffer=NULL;
gsu=NULL;
szTemp=NULL;
tempBuffer=NULL;
if(sk!=INVALID_SOCKET)
{
WSAAsyncSelect(sk,Handle,0,0);
closesocket(sk);
sk=INVALID_SOCKET;
}
bListen=false;
maxChaters=0;
Perform(WM_VSCROLL,SB_TOP,0);
LineAdd(0,"已经退出监听状态!");
}
bool GServer::Accept(SOCKET tsk)
{
if(tsk!=sk)return false;
sockaddr_in sock;
int socklen=sizeof(sockaddr_in),i;
for(i=0;i<maxChaters;i++)
if(gsu[i].sk==INVALID_SOCKET)break;
SOCKET tempsk=accept(tsk,(sockaddr*)&sock,&socklen);
id++;
//sprintf(szTemp,"来自%s的连接请求!分配ID:%d",inet_ntoa(sock.sin_addr),++id);
//LineAdd(szTemp);
if(FOnConnecting)FOnConnecting(this);
if(bDoorClose)
{
send(tempsk,&CloseRefuse,1,0);
closesocket(tempsk);
TListItem*tli=lv->Items->Add();//ID,呢称,IP,状态,接收字节数,发送字节数
tli->Caption=id;
tli->SubItems->Add("未知");
tli->SubItems->Add(inet_ntoa(sock.sin_addr));
tli->SubItems->Add("关门拒绝!");
tli->SubItems->Add("0");
tli->SubItems->Add("1");
// sprintf(szTemp,"因为已经关门,拒绝了ID:%d的连接请求!",id--);
// LineAdd(szTemp);
return false;
}
if(i>=maxChaters)
{
PGSU tgsu=new GServerUnit[maxChaters*2];
ZeroMemory(tgsu,sizeof(GServerUnit)*maxChaters*2);
memcpy(tgsu,gsu,sizeof(GServerUnit)*maxChaters);
maxChaters+=maxChaters;
delete[]gsu;
gsu=tgsu;
}
if(bImidiate)setsockopt(gsu[i].sk,IPPROTO_TCP,TCP_NODELAY,(char*)&bImidiate,sizeof(BOOL));
gsu[i].Comfirmed=false;
gsu[i].ai.id=id;
gsu[i].canWrite=true;
gsu[i].sk=tempsk;
strcpy(gsu[i].ai.Name,"<未验证>");
gsu[i].SBuffer=new char[4097];
gsu[i].RBuffer=new char[2049];
gsu[i].SBufferSize=4096;
gsu[i].rbytes=0;
gsu[i].sbytes=0;
gsu[i].curSSize=0;
gsu[i].curRSize=0;
gsu[i].li=lv->Items->Add();//ID,呢称,IP,状态,接收字节数,发送字节数
gsu[i].li->Caption=id;
gsu[i].li->SubItems->Add(gsu[i].ai.Name);
gsu[i].li->SubItems->Add(inet_ntoa(sock.sin_addr));
gsu[i].li->SubItems->Add("等待验证!");
gsu[i].li->SubItems->Add(gsu[i].rbytes);
gsu[i].li->SubItems->Add(gsu[i].sbytes);
if(WSAAsyncSelect(tempsk,Handle,WM_CHATSERVER,FD_READ|FD_WRITE|FD_CLOSE)==SOCKET_ERROR)
{Leave(i);return false;}
return true;
}
bool GServer::Read(SOCKET tsk)
{
int i=indexBySocket(tsk);
if(i<0)return false;
if(WSAAsyncSelect(tsk,Handle,WM_CHATSERVER,FD_WRITE|FD_CLOSE)==SOCKET_ERROR)
{Leave(i);return false;}
if(gsu[i].curRSize<0)gsu[i].curRSize=0;
int iRet=recv(tsk,gsu[i].RBuffer+gsu[i].curRSize,RBufferSize-gsu[i].curRSize,0);
if(iRet<=0){Leave(i);return false;}
/*FILE*fp=fopen("text.txt","wb+");
fwrite(gsu[i].RBuffer+gsu[i].curRSize,sizeof(char),iRet,fp);
fclose(fp);*/
gsu[i].rbytes+=iRet;
gsu[i].li->SubItems->Strings[LIRBYTES]=gsu[i].rbytes;
gsu[i].curRSize+=iRet;
tBuffer=gsu[i].RBuffer;
int nSize=(zeroInt&tBuffer[0]),nPos=0;
while(gsu[i].curRSize>=nSize)
{
if(gsu[i].Comfirmed)
{memcpy(SRBuffer+nPos,tBuffer,nSize);nPos+=nSize;}
else
{
memcpy(szTemp,tBuffer,nSize);
if(!Comfirm((PPINFO)(szTemp+1),i)){Leave(i);return false;}
nPos=15+dhSize;
}
gsu[i].curRSize-=nSize;
if(gsu[i].curRSize<=0)break;
tBuffer=(tBuffer+nSize);nSize=(zeroInt&tBuffer[0]);
}
if(nPos>0)SendAll(nPos);
if(gsu[i].curRSize>0){memcpy(szTemp,tBuffer,gsu[i].curRSize);memcpy(gsu[i].RBuffer,szTemp,gsu[i].curRSize);}
if(WSAAsyncSelect(tsk,Handle,WM_CHATSERVER,FD_READ|FD_WRITE|FD_CLOSE)==SOCKET_ERROR)
{Leave(i);return false;}
return true;
}
bool GServer::AddBuffer(int i,int len)
{
if(gsu[i].curSSize<0)gsu[i].curSSize=0;
if(len>(gsu[i].SBufferSize-gsu[i].curSSize))
{
if(len>gsu[i].SBufferSize)gsu[i].SBufferSize+=len;
else
gsu[i].SBufferSize=gsu[i].SBufferSize*2;
if(gsu[i].SBufferSize>=20*1024){Leave(i);return false;}
tBuffer=new char[gsu[i].SBufferSize+1];
memcpy(tBuffer,gsu[i].SBuffer,gsu[i].curSSize);
delete[]gsu[i].SBuffer;
gsu[i].SBuffer=tBuffer;
}
memcpy(gsu[i].SBuffer+gsu[i].curSSize,SRBuffer,len);
gsu[i].curSSize+=len;
return true;
}
void GServer::SendAll(int len)
{
for(int i=0;i<maxChaters;i++)
{
if(gsu[i].sk==INVALID_SOCKET||gsu[i].Comfirmed==false||AddBuffer(i,len)==false)continue;
Send(i);
}
}
void GServer::Send(int index)
{
if(index<0||gsu[index].canWrite==false||gsu[index].sk==INVALID_SOCKET)return;
if(gsu[index].curSSize<=0){gsu[index].curSSize=0;return;}
int len=send(gsu[index].sk,gsu[index].SBuffer,gsu[index].curSSize,0);
if(len==SOCKET_ERROR)
{
if(WSAGetLastError()==WSAEWOULDBLOCK)gsu[index].canWrite=false;
else
Leave(index);
return;
}
gsu[index].curSSize-=len;
if(gsu[index].curSSize>0)
{
if(gsu[index].curSSize>tBufferSize)
{
tBuffer=new char[gsu[index].curSSize+1];
delete[]tempBuffer;
tempBuffer=tBuffer;
tBufferSize=gsu[index].curSSize;
}
memcpy(tempBuffer,gsu[index].SBuffer+len,gsu[index].curSSize);
memcpy(gsu[index].SBuffer,tempBuffer,gsu[index].curSSize);
}
gsu[index].sbytes+=len;
gsu[index].li->SubItems->Strings[LISBYTES]=gsu[index].sbytes;
}
void __fastcall GServer::SetImidiate(BOOL isi)
{
bImidiate=isi;
if(bListen==false)return;
for(int i=0;i<maxChaters;i++)
{
if(gsu[i].sk==INVALID_SOCKET)continue;
setsockopt(gsu[i].sk,IPPROTO_TCP,TCP_NODELAY,(char*)&isi,sizeof(BOOL));
}
}
void GServer::Leave(int index)
{
if(index<0||index>=maxChaters||gsu[index].sk==INVALID_SOCKET)return;
WSAAsyncSelect(gsu[index].sk,Handle,0,0);
closesocket(gsu[index].sk);
gsu[index].sk=INVALID_SOCKET;
if(gsu[index].Comfirmed)
gsu[index].li->SubItems->Strings[LISTATUS]="连接断开!";
else
gsu[index].li->SubItems->Strings[LISTATUS]="验证失败!";
if(gsu[index].SBuffer)delete[] gsu[index].SBuffer;
if(gsu[index].RBuffer)delete[] gsu[index].RBuffer;
gsu[index].SBuffer=NULL;
gsu[index].RBuffer=NULL;
gsu[index].curSSize=0;
gsu[index].curRSize=0;
gsu[index].li->SubItems->Strings[LIRBYTES]=gsu[index].rbytes;
gsu[index].li->SubItems->Strings[LISBYTES]=gsu[index].sbytes;
if(gsu[index].Comfirmed)
{
int dellen=6+dhSize;
for(int i=0;i<maxChaters;i++)
{
if(gsu[i].sk==INVALID_SOCKET||gsu[i].Comfirmed==false)continue;
pdhchar=gsu[i].SBuffer+gsu[i].curSSize;
pdh=(PDATAHEADER)pdhchar;
pdh->cbsize=dellen;
pdh->cmd=3;
pdh->id=gsu[index].ai.id;
pdh->toid=gsu[index].ai.id;
pdh->color=(TColor)clRed;
strcpy(pdhchar+dhSize,"886!");
gsu[i].curSSize+=dellen;
Send(i);
}
}
gsu[index].ai.id=0;
gsu[index].Comfirmed=false;
if(FOnLeave)FOnLeave(this);
return;
}
void GServer::LeaveAll()
{
for(int i=0;i<maxChaters;i++)
Leave(i);
closesocket(sk);
sk=INVALID_SOCKET;
bListen=false;
maxChaters=0;
}
void GServer::ListInfo()
{
int i,j=0;
Perform(WM_VSCROLL,SB_TOP,0);
LineAdd(0,"");
for(i=0;i<maxChaters;i++)
{
if(gsu[i].sk==INVALID_SOCKET)continue;
j++;
sprintf(szTemp,"ID:%d,呢称:%s\r\n 接收缓冲:%d字节,发送缓冲:%d字节!",
gsu[i].ai.id,gsu[i].ai.Name,RBufferSize,gsu[i].SBufferSize);
LineAdd(0,szTemp);
}
sprintf(szTemp,"在线:共%d人\r\n临时缓冲:%d字节,系统缓冲%d字节!",j,tBufferSize,4096);
LineAdd(0,szTemp);
//Perform(WM_VSCROLL,SB_BOTTOM,0);
//this->Refresh();
}
void GServer::Kick(int tid)
{
Leave(indexByID(tid));
}
bool GServer::Comfirm(PPINFO ppi,int index)
{
if(strcmp(Password.c_str(),ppi->Password))return false;
gsu[index].Comfirmed=true;
memcpy(gsu[index].ai.Name,ppi->Name,15);
gsu[index].ai.Face=ppi->Face;
gsu[index].ai.Name[14]='\0';
//接下来加入LV中:
gsu[index].li->SubItems->Strings[LISTATUS]=AnsiString("通过验证!");
gsu[index].li->SubItems->Strings[LINAME]=AnsiString(gsu[index].ai.Name);
//
int tsiSize=(15+dhSize)*Chaters();
if(tsiSize>(gsu[index].SBufferSize-128))
{
//扩大缓冲区
tBuffer=new char[tsiSize+1];
delete[]gsu[index].SBuffer;
gsu[index].SBuffer=tBuffer;
gsu[index].SBufferSize=tsiSize;
}
pdh=(PDATAHEADER)gsu[index].SBuffer;
pdh->cbsize=dhSize+WelcomMessage.Length();
pdh->cmd=1;
pdh->id=gsu[index].ai.id;
pdh->toid=gsu[index].ai.id;//在返回ID时为了安全,将ID,TOID都设为ID
pdh->color=(TColor)clRed;
memcpy(gsu[index].SBuffer+dhSize,WelcomMessage.c_str(),WelcomMessage.Length());
gsu[index].curSSize=pdh->cbsize;
for(int i=0;i<maxChaters;i++)
{
if(gsu[i].sk==INVALID_SOCKET||i==index||gsu[i].Comfirmed==false)continue;
pdhchar=gsu[index].SBuffer+gsu[index].curSSize;
pdh=(PDATAHEADER)pdhchar;
pdh->cbsize=15+dhSize;
pdh->cmd=2;
pdh->id=gsu[i].ai.id;
pdh->toid=gsu[i].ai.Face;
pdh->color=(TColor)clBlue;
memcpy(pdhchar+dhSize,gsu[i].ai.Name,15);
gsu[index].curSSize+=pdh->cbsize;
}
pdh=(PDATAHEADER)SRBuffer;
pdh->cbsize=15+dhSize;
pdh->cmd=2;
pdh->id=gsu[index].ai.id;
pdh->toid=gsu[index].ai.Face;//用TOID来存放FACE;
pdh->color=(TColor)clNavy;
memcpy(SRBuffer+dhSize,gsu[index].ai.Name,15);
return true;
}
int GServer::Chaters()
{
int j=0;
for(int i=0;i<maxChaters;i++)
if(gsu[i].sk!=INVALID_SOCKET&&gsu[i].Comfirmed)j++;
return j;
}
int GServer::indexBySocket(SOCKET tsk)
{
if(tsk==INVALID_SOCKET)return -1;
for(int i=0;i<maxChaters;i++)
if(tsk==gsu[i].sk)return i;
return -1;
}
int GServer::indexByID(int tid)
{
for(int i=0;i<maxChaters;i++)
if(gsu[i].sk!=INVALID_SOCKET&&tid==gsu[i].ai.id)return i;
return -1;
}
void __fastcall GServer::HandleChat(TMessage&msg)
{
static int hci;
static SOCKET wsk;
wsk=(SOCKET)msg.WParam;
if(wsk!=sk)
{
hci=indexBySocket(wsk);
if(hci<0){closesocket(wsk);return;}
if(msg.LParamHi){Leave(hci);return;}
}
else if(wsk==sk&&msg.LParamHi)
{DisConnect();return;}
switch(msg.LParamLo)
{
case FD_ACCEPT:
Accept(wsk);
break;
case FD_READ:
Read(wsk);
break;
case FD_WRITE:
Send(hci);
break;
case FD_CLOSE:
Leave(hci);
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -