www.gusucode.com > 基于VC++的局域网视频聊天系统源码程序 > 基于VC++的局域网视频聊天系统源码程序/code/ChatClient/DSocket.cpp

    // DSocket.cpp: implementation of the DSocket class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ChatClientDlg.h"
#include "DSocket.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

char DSocket::remoteaddress[512]="";
char DSocket::remotename[512]="";

DSocket::DSocket()
{
	m_dlen=0;
	m_data = new char[IMAGE_WIDTH * IMAGE_HEIGHT*10];
	memset(m_data, 0, IMAGE_WIDTH * IMAGE_HEIGHT*10);
	if(!m_data) AfxMessageBox("DSocket::DSocket 分配缓冲失败");
	else m_dlen=IMAGE_WIDTH * IMAGE_HEIGHT*10;
}

DSocket::~DSocket()
{
	if(m_data)	delete []m_data;
	m_dlen=0;
}

BOOL DSocket::CreateSocket(int port, int dtype)
{
	type=dtype;
	gethostname(localname,512);	
	switch(type)
	{
	case TYPE_CONTROL:
		rmtport = PORT_CONTROL;
		break;
	case TYPE_AUDIO:
		rmtport=PORT_AUDIO;
		break;
	case TYPE_VIDEO:
		rmtport=PORT_VIDEO;
		break;
	default:
		rmtport=0;
	}
	return Create(port,SOCK_DGRAM);

}

void DSocket::SetParent(CDialog *dlg)
{
	pDlg=dlg;
}

BOOL DSocket::SendControlMessage(int type, char *address)
{
	int n;
	BOOL	ret;
	m_data[0]=type;				

	// Length of hostname
	n=strlen(localname);	
	m_data[1]=n;					
	
	// Name of the sender host

	memcpy(&m_data[2],localname,n);

	switch(type)
	{
	case MESG_CONNECT:
		break;
	case MESG_DISCONNECT:
		break;
	case MESG_ACCEPT:
		break;
	case MESG_REJECT:
		break;
	default:
		break;
	}

	if(address==NULL)
	{
		ret=SendTo(m_data,n+2,rmtport,remoteaddress);
	}else
	{
		ret=SendTo(m_data,n+2,rmtport,address);
	}
	return (ret!=SOCKET_ERROR);

}

void DSocket::SendAudioData(unsigned char *data, int length)
{
	if(strlen(remoteaddress)<=1)
	{
		CopyMemory(remoteaddress,((CChatClientDlg *)pDlg)->dcontrol .remoteaddress,sizeof(remoteaddress));
		CopyMemory(remotename,((CChatClientDlg *)pDlg)->dcontrol .remotename,sizeof(remotename));
	}
	SendTo(data,length,rmtport,remoteaddress);

}

void DSocket::SendVideoData(unsigned char *data, int length)
{
	if(strlen(remoteaddress)<=1)
	{
		CopyMemory(remoteaddress,((CChatClientDlg *)pDlg)->dcontrol .remoteaddress,sizeof(remoteaddress));
		CopyMemory(remotename,((CChatClientDlg *)pDlg)->dcontrol .remotename,sizeof(remotename));
	}
	Sleep(1);
	int iRet=SendTo(data,length,rmtport,remoteaddress);
	DWORD dw=GetLastError();

}

void DSocket::OnReceive(int errcode)
{
	CString address,tmp;
	BOOL	ret=TRUE;
	char hname[512],str[1024];
	unsigned int port=0,retvalue=SOCKET_ERROR;
	int n=0,len=0;
	int ulen=0;

	if(type==TYPE_CONTROL)
	{
	//	TRACE("DSocket::OnReceive,TYPE_CONTROL,");
		retvalue= ReceiveFrom(m_data,m_dlen,address,port);

		if(retvalue==SOCKET_ERROR && ((CChatClientDlg*)pDlg)->m_State==STATE_CALLOUT)
		{
			((CChatClientDlg*)pDlg)->m_State = STATE_IDLE;
			((CChatClientDlg*)pDlg)->DestroyVideo();
			return;
		}
		else 
			if(retvalue==SOCKET_ERROR)	return;
		
		// Get host name from the data.	
		for(int i=0;i<m_data[1];i++)
			hname[i]=m_data[i+2];
		hname[i]=0;

		switch(m_data[0])
		{
			// action   : Remote user has sent the invitation for conference
			// reaction : accept(/reject) the invitation
			case MESG_CONNECT:
				((CChatClientDlg*)pDlg)->m_State=STATE_CALLIN;
                tmp.Format ("用户 %s 请求连接.\n是否接受该连接?",hname);
				ret=AfxMessageBox(tmp,MB_OKCANCEL);
				if(ret!=IDOK)
				{
					tmp=address;
					strcpy(remoteaddress,(LPCTSTR)address);
					((CChatClientDlg*)pDlg)->dcontrol.SendControlMessage(MESG_REJECT,remoteaddress);
					strcpy(remoteaddress,(LPCTSTR)tmp);
					return;
				}
			
				// maybe wait timeout here,should check it
				if(((CChatClientDlg*)pDlg)->m_State==STATE_IDLE) return;
				strcpy(remotename,hname);
				strcpy(remoteaddress,(LPCTSTR)address);
				rmtport = port;
				((CChatClientDlg*)pDlg)->StartVideo();
				((CChatClientDlg*)pDlg)->dcontrol.SendControlMessage(MESG_ACCEPT,remoteaddress);
				sprintf(str,"用户 %s 已连接",hname);
				return;
			// action   : Remote user has disconnected
			// reaction : destroy the conference
			case MESG_DISCONNECT:
				if(	((CChatClientDlg*)pDlg)->m_bStart)
				{
					((CChatClientDlg*)pDlg)->DestroyVideo();
				}
			return;
			// action   : Remote user has accepted the invitation
			// reaction : start the conference
			case MESG_ACCEPT:
				if(	((CChatClientDlg*)pDlg)->m_State==STATE_CALLOUT || //FALSE)
					((CChatClientDlg*)pDlg)->m_State==STATE_CALLIN )//for local test,commect this while build release version
				{
					strcpy(remotename,hname);
					strcpy(remoteaddress,(LPCTSTR)address);
					((CChatClientDlg*)pDlg)->StartVideo();
				}
				return;
			// action   : Remote user has rejected the invitation
			// reaction : what to do...?
			case MESG_REJECT:
				if(	((CChatClientDlg*)pDlg)->m_State!=STATE_CONNECTED)
				{
					((CChatClientDlg*)pDlg)->DestroyVideo();

				}
				return;
			default:
				return;
		}
		return;
	}

	if(type==TYPE_AUDIO)
	{
		retvalue=this->ReceiveFrom(m_data,m_dlen,address,port);
		if(retvalue==SOCKET_ERROR)	return;
		rmtport = port;
		((CChatClientDlg*)pDlg)->m_G729aCompress .UnCompress (
				(char *)m_data,retvalue,
				((CChatClientDlg*)pDlg)->m_AUnComped,
				&ulen );
		if(ulen>0)
			((CChatClientDlg *)pDlg)->m_AudioPlay->PostThreadMessage(WM_PLAYSOUND_PLAYBLOCK,ulen,(LPARAM)((CChatClientDlg*)pDlg)->m_AUnComped);
		return;
	}

	if(type==TYPE_VIDEO)
	{
		retvalue=ReceiveFrom(m_data,m_dlen,address,port);
		if(retvalue==SOCKET_ERROR)			return;
		rmtport = port;
		((CChatClientDlg *)pDlg)->m_VideoCodec.DecodeVideoData(
			m_data,
			retvalue,
			((CChatClientDlg *)pDlg)->m_VUnComped,
			&ulen,
			0);
		if(ulen>0)
			((CChatClientDlg *)pDlg)->m_LocalDlg.DisplayRemoteFrame((unsigned char*)(((CChatClientDlg *)pDlg)->m_VUnComped),ulen);
		return;
	}

}

void DSocket::CloseSocket()
{
	DSocket::Close();
}