⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gclient.cpp

📁 网络极速寻呼源码
💻 CPP
字号:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <stdio.h>
#include "GClient.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//

static inline void ValidCtrCheck(GClient *)
{
	new GClient(NULL);
}
//---------------------------------------------------------------------------
__fastcall GClient::GClient(TComponent* Owner)
	: TRichEdit(Owner)
{
canWrite=false;
bConnected=false;
id=0;
sk=INVALID_SOCKET;
RBuffer=NULL;
SRBuffer=NULL;
tBuffer=NULL;
szTemp=NULL;
gcu=NULL;
RSize=2048;
tSize=4096;
SRSize=4096;
maxChaters=20;
curRSize=0;
curSRSize=0;
zeroInt=0xff;
colortext=(TColor)clNavy;
dhSize=sizeof(DataHeader);
bbisi=true;
}
//---------------------------------------------------------------------------
namespace Gclient
{
	void __fastcall PACKAGE Register()
	{
		TComponentClass classes[1] = {__classid(GClient)};
		RegisterComponents("GControl", classes, 0);
	}
}
//---------------------------------------------------------------------------
bool GClient::Connect()
{
if(sk!=INVALID_SOCKET)Close();
curRSize=0;
curSRSize=0;
sock.sin_family=AF_INET;
sock.sin_addr.s_addr=ip;
sock.sin_port=htons(Port);
int iRet,tiRet;
try
{
sk=socket(AF_INET,SOCK_STREAM,0);
if(sk==INVALID_SOCKET)throw 0;
if(WSAAsyncSelect(sk,Handle,WM_CHATCLIENT,FD_CONNECT|FD_CLOSE|FD_READ|FD_WRITE)==SOCKET_ERROR)throw 6;
Lines->Add("正在初始化连接......");
iRet=connect(sk,(sockaddr*)&sock,sizeof(sockaddr_in));
if(iRet==SOCKET_ERROR)
	{
	tiRet=WSAGetLastError();
	if(tiRet==WSAEWOULDBLOCK){Lines->Add("正在与服务器连接......");return true;}
	else if(tiRet==WSAECONNREFUSED)throw 2;
	else if(tiRet==WSAENETUNREACH)throw 3;
	else throw 4;
	}
else if(iRet==0)
	return true;
}
catch(int Error)
{
switch(Error)
{
case 0:Lines->Add("初始化连接失败!");break;
case 2:Lines->Add("目标主机上并未开放此端口!");break;
case 3:Lines->Add("无法访问网络!");break;
case 4:Lines->Add("未知的Winsock错误!");break;
case 6:Lines->Add("选择异步消息模式失败!");break;
}
if(FOnConnectFailed)FOnConnectFailed(this);
}
catch(...){}
if(sk!=INVALID_SOCKET){WSAAsyncSelect(sk,Handle,0,0);closesocket(sk);}
return false;
}

void GClient::Write(char*wBuffer,int size,int toid)
{
if(size>81)size=81;
if(curSRSize<0)curSRSize=0;
if((SRSize-curSRSize)<size)
	{
	SRSize+=1024;
	char*tempBuffer=new char[SRSize+1];
	memcpy(tempBuffer,SRBuffer,curSRSize);
	delete[]SRBuffer;
	SRBuffer=tempBuffer;	
	}
pdhchar=SRBuffer+curSRSize;
pdh=(PDATAHEADER)pdhchar;
pdh->cbsize=size+dhSize;
pdh->color=colortext;
pdh->cmd=0;
pdh->id=id;//源ID
pdh->toid=toid;//目标ID
curSRSize+=dhSize;
memcpy(SRBuffer+curSRSize,wBuffer,size);
curSRSize+=size;
if(canWrite==false)return;
Send();
}

void GClient::Send()
{
if(curSRSize<=0){curSRSize=0;return;}
int iRet=send(sk,SRBuffer,curSRSize,0);
if(iRet==SOCKET_ERROR)
	{
	if(WSAGetLastError()==WSAEWOULDBLOCK)
	canWrite=false;
	else
	{Close();return;}
	}
else if(iRet<curSRSize)
	{
	curSRSize-=iRet;
	if(curSRSize>tSize){tSize+=curSRSize;char*tempBuffer=new char[tSize+1];delete[]tBuffer;tBuffer=tempBuffer;}
	memcpy(tBuffer,SRBuffer+iRet,curSRSize);
	memcpy(SRBuffer,tBuffer,curSRSize);
	}
else
	curSRSize=0;
}

void GClient::SendInfo()
{
curSRSize=sizeof(PInfo)+1;
SRBuffer[0]=curSRSize;
memcpy(SRBuffer+1,&pi,curSRSize-1);
Send();
}

void GClient::Read()
{
static int nSize,i,j;
if(curRSize<0)curRSize=0;
int iRet=recv(sk,RBuffer+curRSize,RSize-curRSize,0);
if(iRet<=0){Close();return;}
curRSize+=iRet;
char*tempBuffer=RBuffer;
nSize=(zeroInt&tempBuffer[0]);
if(nSize==1){Lines->Add("对方已经关门!你被拒绝了!");Close();return;}
while(curRSize>=nSize)
{
memcpy(szTemp,tempBuffer,nSize);
szTemp[nSize]='\0';pdh=(PDATAHEADER)szTemp;
switch(pdh->cmd)
{
case 0:
	if(pdh->toid&&pdh->toid!=id&&pdh->id!=id)break;
	i=indexByID(pdh->id);
	if(i==-1)break;
	if(pdh->toid)
		{
		j=indexByID(pdh->toid);
		if(j==-1)break;
		sprintf(tBuffer,"%s(%d)悄悄地对%s(%d)说:%s",
				gcu[i].ai.Name,gcu[i].ai.id,gcu[j].ai.Name,gcu[j].ai.id,szTemp+dhSize);
		}
	else
		sprintf(tBuffer,"%s(%d):%s",gcu[i].ai.Name,gcu[i].ai.id,szTemp+dhSize);
	SelAttributes->Color=pdh->color;
	Lines->Add(tBuffer);
	if(FOnSay)FOnSay(this);
	break;
case 1://返回ID
	if(pdh->toid!=pdh->id){Lines->Add("服务端返回无效的ID!");Close();break;}
	id=pdh->toid;
	sprintf(tBuffer,"服务端返回ID:%d\r\n%s",pdh->toid,szTemp+dhSize);
	SelAttributes->Color=pdh->color;
	Lines->Add(tBuffer);
	this->Perform(WM_VSCROLL,SB_LINEDOWN,0);
	break;
case 2://加人!
	 if(pdh->id==0||indexByID(pdh->id)!=-1)break;
	 for(i=0;i<maxChaters;i++)
		if(gcu[i].ai.id ==0)break;
	 if(i>=maxChaters)
	 {//扩大maxChaters;
		PGCU tgcu=new GClientUnit[maxChaters*2];
		ZeroMemory(tgcu,sizeof(GClientUnit)*maxChaters*2);
		memcpy(tgcu,gcu,sizeof(GClientUnit)*maxChaters);
		delete[]gcu;
		gcu=tgcu;
		maxChaters+=maxChaters;
	 }
	 gcu[i].ai.id =pdh->id;
	 memcpy(gcu[i].ai.Name,szTemp+dhSize,15);
	 gcu[i].ai.Name[14]='\0';
	 if(pdh->toid>=0&&pdh->toid<65)
	 gcu[i].ai.Face=pdh->toid;
	 else
	 gcu[i].ai.Face=0;
	 tButton=new TToolButton(NULL);
	 tButton->ImageIndex =gcu[i].ai.Face;
	 //tButton->Caption =AnsiString(gcu[i].ai.Name);
	 sprintf(tBuffer,"呢称:%s\nID号:%d",gcu[i].ai.Name,gcu[i].ai.id);
	 tButton->Hint =AnsiString(tBuffer);
	 tButton->ShowHint =true;
	 tButton->Tag =gcu[i].ai.id;
	 tButton->Caption=gcu[i].ai.Name;
	 tButton->OnClick=FOnButtonClick;
	 tButton->SetToolBar(lv);
	 sprintf(tBuffer,"%s(%d)正在聊天室!",gcu[i].ai.Name,gcu[i].ai.id);
	 SelAttributes->Color=pdh->color;
	 Lines->Add(tBuffer);
	 this->Perform(WM_VSCROLL,SB_LINEDOWN,0);
	 break;
case 3://删人!
	if(pdh->toid!=pdh->id){Lines->Add("服务器返回无效的ID!");break;}
	i=indexByID(pdh->id);
	for(j=0;j<lv->ButtonCount;j++)
		if(pdh->id==lv->Buttons[j]->Tag)break;
	if(i==-1||j>=lv->ButtonCount)break;
	delete lv->Buttons[j];
	sprintf(tBuffer,"%s(%d)离开了聊天室!%s",gcu[i].ai.Name,gcu[i].ai.id,szTemp+dhSize);
	SelAttributes->Color=pdh->color;
	Lines->Add(tBuffer);
	gcu[i].ai.id =0;
	break;
}
this->Perform(WM_VSCROLL,SB_LINEDOWN,0);
curRSize-=nSize;
tempBuffer=tempBuffer+nSize;
if(curRSize<=0){curRSize=0;break;}
nSize=(zeroInt&tempBuffer[0]);
}
if(curRSize>0&&tempBuffer!=RBuffer)
{memcpy(tBuffer,tempBuffer,curRSize);memcpy(RBuffer,tBuffer,curRSize);}
//Perform(WM_VSCROLL,SB_BOTTOM,0);
//this->Refresh();
}

void GClient::Close()
{
canWrite=false;
id=0;
curRSize=0;
curSRSize=0;
if(sk!=INVALID_SOCKET)
{WSAAsyncSelect(sk,Handle,0,0);closesocket(sk);}
sk=INVALID_SOCKET;
if(RBuffer)delete[]RBuffer;
RBuffer=NULL;
if(SRBuffer)delete[]SRBuffer;
SRBuffer=NULL;
if(tBuffer)delete[]tBuffer;
tBuffer=NULL;
if(szTemp)delete[]szTemp;
szTemp=NULL;
for(int i=0;i++;i<maxChaters)
{
if(gcu[i].ai.id==0)continue;
//delete[]gcu[i].li;
}
if(gcu)delete[]gcu;
while(lv->ButtonCount>1)
	if(lv->Buttons[0]->Tag>0)
		delete lv->Buttons[0];
	else
		delete lv->Buttons[1];

gcu=NULL;
RSize=2048;
tSize=4096;
SRSize=4096;
maxChaters=20;
if(bConnected&&FOnClosed)FOnClosed(this);
bConnected=false;
}
void __fastcall GClient::HandleChat(TMessage&msg)
{
if(msg.LParamHi)
{
switch(msg.LParamHi)
{
case WSAECONNREFUSED:
	Lines->Add("错误:目标主机上并未开放此端口!");
	if(FOnConnectFailed)FOnConnectFailed(this);
	break;
case WSAENETUNREACH:Lines->Add("错误:网络访问不可到达!");
	if(FOnConnectFailed)FOnConnectFailed(this);
	break;
case WSAENETDOWN:Lines->Add("严重错误:网络子系统失败!");
	if(FOnConnectFailed)FOnConnectFailed(this);
	break;
}
Close();
return;
}
switch(msg.LParamLo)
{
 case FD_CONNECT:
	 bConnected=true;
	 setsockopt(sk,IPPROTO_TCP,TCP_NODELAY,(char*)&bbisi,sizeof(BOOL));
	 RBuffer=new char[RSize+1];
	 tBuffer=new char[tSize+1];
	 SRBuffer=new char[SRSize+1];
	 szTemp=new char[256];
	 gcu=new GClientUnit[maxChaters];
	 ZeroMemory(gcu,sizeof(GClientUnit)*maxChaters);
	 ZeroMemory(RBuffer,RSize+1);
	 ZeroMemory(tBuffer,tSize+1);
	 ZeroMemory(SRBuffer,SRSize+1);
	 ZeroMemory(szTemp,256);
	 Lines->Add("已经建立了连接!等待服务器验证......");
	if(FOnConnected)FOnConnected(this);
	 SendInfo();
	 break;
 case FD_WRITE:
	canWrite=true;
	Send();
	break;
 case FD_READ:
	Read();
	break;
 case FD_CLOSE:
	Close();
	break;
}
}

int GClient::indexByID(int tid)
{
for(int i=0;i<maxChaters;i++)
{
 if(tid==gcu[i].ai.id)return i;
}
return -1;
}

⌨️ 快捷键说明

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