www.pudn.com > TestIPMSG.rar > ChatWidnowDlg.cpp


// ChatWidnowDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "TestIPMSG.h" 
#include "ChatWidnowDlg.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatWidnowDlg dialog 
 
extern vector g_AcceptClient;  /// 
 
CChatWidnowDlg::CChatWidnowDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CChatWidnowDlg::IDD, pParent), 
	m_bDFirst(FALSE), 
	m_bLFirst(FALSE), 
	m_chatPort(0), 
	m_bNet(FALSE), 
	m_serialNum(0), 
	m_bNetPort(FALSE) 
{ 
	//{{AFX_DATA_INIT(CChatWidnowDlg) 
	m_sMsg = _T(""); 
	m_ClientInfoLB = _T(""); 
	//}}AFX_DATA_INIT 
} 
 
 
void CChatWidnowDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CChatWidnowDlg) 
	DDX_Text(pDX, IDC_EDIT1, m_sMsg); 
	DDX_Text(pDX, IDC_EDIT2, m_ClientInfoLB); 
	//}}AFX_DATA_MAP 
} 
 
 
BEGIN_MESSAGE_MAP(CChatWidnowDlg, CDialog) 
	//{{AFX_MSG_MAP(CChatWidnowDlg) 
	ON_BN_CLICKED(IDOK, OnSendMsg) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CChatWidnowDlg message handlers 
 
BOOL CChatWidnowDlg::OnInitDialog()  
{ 
	CDialog::OnInitDialog(); 
	 
	// TODO: Add extra initialization here 
	DWORD dwNameLen = sizeof(m_szMyLocalName); 
	GetUserName((LPTSTR)m_szMyLocalName,&dwNameLen); 
 
	if ( m_curChatName != NULL) 
	{ 
		char curDescripChat[80]; 
		sprintf(curDescripChat,"你正在和%s聊天",m_curChatName); 
		 
		if ( m_curChatName != NULL ) 
			SetWindowText(_T(curDescripChat)); 
	} 
 
	if ( m_bNet == TRUE ) 
	{ 
		char lpszHeader[NET_TRANSMIT_BUFFER]; 
		char lpszChatContent[NET_TRANSMIT_BUFFER]; 
		ChatDataInfo *chatDataInfo = (ChatDataInfo *)m_firstContent; 
	 
		sprintf(lpszHeader,"%s:%s",chatDataInfo->m_clientName,chatDataInfo->m_curSysTimer); 
		sprintf(lpszChatContent,"%s",chatDataInfo->m_curChatData); 
		ShowText(lpszHeader,lpszChatContent); 
	} 
 
	StartChatServerThread(); ///// 
	return TRUE;  // return TRUE unless you set the focus to a control 
	              // EXCEPTION: OCX Property Pages should return FALSE 
} 
void CChatWidnowDlg::SendDataToClient(char *sendBuf) 
{ 
	if ( sendBuf != NULL ) 
	{ 
		vector::iterator ts; 
		for ( ts = g_AcceptClient.begin(); ts != g_AcceptClient.end(); ts ++ ) 
		{ 
			if ( strcmp(ts->m_loginName,m_curChatName) == 0 ) 
			{ 
				break; 
			} 
		} 
 
		if ( ts == g_AcceptClient.end() ) 
		{ 
			AfxMessageBox("对方已经下线!"); 
			return; 
		} 
		 
		SOCKADDR_IN addrSend; 
		addrSend.sin_addr.S_un.S_addr = inet_addr(ts->m_ClientIPAddr); 
		addrSend.sin_family = AF_INET; 
		addrSend.sin_port = htons(NET_CHAT_PORT + m_chatPort); 
 
		int isend = sendto(m_ChatServerSocket,sendBuf,NET_TRANSMIT_BUFFER,0,(struct sockaddr FAR *)&addrSend,sizeof(SOCKADDR_IN)); 
 
		DWORD dwRet = ::WaitForSingleObject(m_hSend,200); 
		if ( dwRet == WAIT_TIMEOUT || isend == SOCKET_ERROR ) 
		{ 
			addrSend.sin_port = htons(NET_CHAT_WINDOW_PORT); 
			isend = sendto(m_ChatServerSocket,sendBuf,NET_TRANSMIT_BUFFER,0,(struct sockaddr FAR *)&addrSend,sizeof(SOCKADDR_IN)); 
			 
			if ( isend == SOCKET_ERROR ) 
			{ 
				AfxMessageBox("发送失败!"); 
				return; 
			} 
		} 
 
		if ( dwRet == WAIT_OBJECT_0 ) 
			ResetEvent(m_hSend); 
	} 
 
} 
 
void CChatWidnowDlg::RecvDataFromClient() 
{ 
	SOCKADDR_IN addrfrom; 
	char RecvChatInfo[NET_TRANSMIT_BUFFER]; 
	 
	int addrLen = sizeof (SOCKADDR_IN); 
 
	int iRecv = recvfrom(m_ChatServerSocket,RecvChatInfo,sizeof(RecvChatInfo),0,(struct sockaddr FAR *)&addrfrom,&addrLen); 
	 
	if ( iRecv == SOCKET_ERROR ) 
	{ 
		TRACE("接收失败!"); 
		return; 
	} 
 
	ProRecvData(RecvChatInfo,addrfrom); 
} 
 
void CChatWidnowDlg::SendQueryChatCommand(char *sendBuf) 
{ 
	ChatDataInfo *DataInfo = (ChatDataInfo *)sendBuf; 
	if ( sendBuf != NULL ) 
	{ 
		vector::iterator ts; 
		for ( ts = g_AcceptClient.begin(); ts != g_AcceptClient.end(); ts ++ ) 
		{ 
			if ( strcmp(ts->m_loginName,m_curChatName) == 0 ) 
			{ 
				break; 
			} 
		} 
 
		if ( ts == g_AcceptClient.end() ) 
		{ 
			AfxMessageBox("对方已经下线!"); 
			return; 
		} 
		 
		SOCKADDR_IN addrSend; 
		addrSend.sin_addr.S_un.S_addr = inet_addr(ts->m_ClientIPAddr); 
		addrSend.sin_family = AF_INET; 
		addrSend.sin_port = htons(NET_CHAT_PORT + m_chatPort);  
 
		int isend = sendto(m_ChatServerSocket,sendBuf,NET_TRANSMIT_BUFFER,0,(struct sockaddr FAR *)&addrSend,sizeof(SOCKADDR_IN)); 
		 
		DWORD dwRet = ::WaitForSingleObject(m_hSend,3000); 
		if ( dwRet == WAIT_TIMEOUT || isend == SOCKET_ERROR ) 
		{ 
			addrSend.sin_port = htons(NET_CHAT_WINDOW_PORT); 
			isend = sendto(m_ChatServerSocket,sendBuf,NET_TRANSMIT_BUFFER,0,(struct sockaddr FAR *)&addrSend,sizeof(SOCKADDR_IN)); 
			 
			if ( isend == SOCKET_ERROR ) 
			{ 
				AfxMessageBox("发送失败!"); 
				return; 
			} 
			ResetEvent(m_hSend); 
		} 
 
		if ( dwRet == WAIT_OBJECT_0 ) 
			ResetEvent(m_hSend); 
 
	} 
} 
 
BOOL CChatWidnowDlg::InitChatServerSocket() 
{ 
	int istat = WSAStartup(MAKEWORD(2,2),&m_wsa); 
 
	if ( istat != 0 ) 
	{ 
		AfxMessageBox("加载winsock失败!"); 
		return FALSE; 
	} 
 
	m_ChatServerSocket = socket(AF_INET,SOCK_DGRAM,0); 
 
	if ( m_ChatServerSocket == INVALID_SOCKET ) 
	{ 
		AfxMessageBox("创建socket失败!"); 
		return FALSE; 
	} 
 
	GetHostIP(m_dwLocalIPAddr); 
	if ( m_bNetPort == TRUE ) 
	{ 
		GetLocalPort(m_chatPort); 
		m_bNetPort = FALSE; 
	} 
	else 
	{ 
		GetChatPort(m_chatPort); 
	} 
 
	m_ChatServerIpAddr.sin_addr.S_un.S_addr = m_dwLocalIPAddr; 
	m_ChatServerIpAddr.sin_family = AF_INET; 
	m_ChatServerIpAddr.sin_port = htons(NET_CHAT_PORT + m_chatPort); 
 
	BOOL bFlag = TRUE; 
	int iset = setsockopt(m_ChatServerSocket,SOL_SOCKET,SO_REUSEADDR,(const char *)&bFlag,sizeof(BOOL)); 
	 
	int iError = WSAGetLastError(); 
	if ( iset == SOCKET_ERROR ) 
	{ 
		TRACE("setsockopting is falied"); 
	} 
 
	int ibind = bind(m_ChatServerSocket,(struct sockaddr FAR *) &m_ChatServerIpAddr,sizeof(SOCKADDR_IN)); 
 
	if ( ibind == SOCKET_ERROR ) 
	{ 
		AfxMessageBox("邦定socket失败!"); 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
void CChatWidnowDlg::GetHostIP(DWORD &dwLocalIP) 
{ 
	struct hostent *thisHost; 
	struct in_addr in; 
	char hostName[80]; 
 
	if ( gethostname(hostName,sizeof(hostName)) == SOCKET_ERROR ) 
	{ 
		AfxMessageBox("取得本地主机名失败!"); 
		return ; 
	} 
 
	if ( hostName != NULL ) 
		thisHost = gethostbyname(hostName); 
 
	int i = 0; 
 
	while ( thisHost->h_addr_list[i] ) 
	{ 
		in.S_un.S_addr = *(unsigned long *)thisHost->h_addr_list[i]; 
		i++; 
	} 
	dwLocalIP = in.S_un.S_addr; 
} 
 
void CChatWidnowDlg::StartChatServerThread() 
{ 
	m_hSend = CreateEvent(NULL,TRUE,TRUE,NULL); 
	ResetEvent(m_hSend); 
	HANDLE hChatThread = CreateThread(NULL,0,ChatServerSocketThread,this,CREATE_SUSPENDED,&m_id); 
	ResumeThread(hChatThread); 
} 
 
DWORD CChatWidnowDlg::ChatServerSocketThread(LPVOID lParam) 
{ 
	CChatWidnowDlg * chatDlg  = (CChatWidnowDlg *)lParam; 
 
	BOOL bIni = chatDlg->InitChatServerSocket(); 
 
	if ( bIni == FALSE ) 
		return 0L; 
 
	chatDlg->FastToClient(); 
	FD_SET fdR; 
	struct timeval timeouts; 
 
	timeouts.tv_sec = 1; 
	timeouts.tv_usec = 0; 
 
	while ( true ) 
	{ 
		FD_ZERO(&fdR); 
		FD_SET(chatDlg->m_ChatServerSocket,&fdR); 
 
		switch( select(chatDlg->m_ChatServerSocket + 1, &fdR , NULL ,NULL ,&timeouts) ) 
		{ 
		case -1: 
			break; 
		case 0: 
			break; 
		default: 
			if ( FD_ISSET(chatDlg->m_ChatServerSocket,&fdR) ) 
				chatDlg->RecvDataFromClient(); 
			break; 
		} 
		Sleep(1); 
	} 
	return 0L; 
} 
 
void CChatWidnowDlg::OnSendMsg()  
{ 
	// TODO: Add your control notification handler code here 
	//UpdateData(true); 
	char chatSendBuff[NET_TRANSMIT_BUFFER]; 
	CString curChatContent; 
	SYSTEMTIME sysTimer; 
	GetLocalTime(&sysTimer); 
 
	ChatDataInfo *ChatInfo = new ChatDataInfo; 
	memset(ChatInfo,0,sizeof(ChatDataInfo)); 
	ChatInfo->m_szFlag = (char )0x81; 
	ChatInfo->m_serialNum = m_serialNum ++ ; 
	sprintf(ChatInfo->m_clientName,"%s",m_szMyLocalName); 
 
	sprintf(ChatInfo->m_curSysTimer,"%u-%u-%u %u:%2u:%2u", 
				sysTimer.wYear, 
				sysTimer.wMonth, 
				sysTimer.wDay, 
				sysTimer.wHour, 
				sysTimer.wMinute, 
				sysTimer.wSecond 
				); 
 
	GetDlgItem(IDC_EDIT1)->GetWindowText(m_sMsg); 
	int iMsgLen = m_sMsg.GetLength(); 
	char ContentBuff[NET_TRANSMIT_BUFFER]; 
	strcpy(ContentBuff,m_sMsg.GetBuffer(iMsgLen)); 
	sprintf(ChatInfo->m_curChatData,"%s",ContentBuff); 
 
	int lpbuflen = sprintf(chatSendBuff,"%s:%u-%u-%u %u:%2u:%2u", 
			m_szMyLocalName, 
			sysTimer.wYear, 
			sysTimer.wMonth, 
			sysTimer.wDay, 
			sysTimer.wHour, 
			sysTimer.wMinute,//szMinute, 
			sysTimer.wSecond//szSecond 
			); 
	 
	curChatContent = curChatContent + chatSendBuff + "\n\r" + m_sMsg; 
	if ( m_bDFirst == TRUE ) 
	{ 
		SendQueryChatCommand((char*)ChatInfo); 
	} 
	else 
		SendDataToClient((char*)ChatInfo); //// 
 
	ShowText(chatSendBuff,ContentBuff); 
 
	m_sMsg.ReleaseBuffer(); 
	m_sMsg == _T(""); 
	delete ChatInfo; 
	GetDlgItem(IDC_EDIT1)->SetWindowText(""); 
} 
 
void CChatWidnowDlg::GetChatPort(unsigned short &uPort) 
{ 
	vector::iterator ts; 
	for ( ts = g_AcceptClient.begin(); ts != g_AcceptClient.end(); ts ++ ) 
	{ 
		if ( strcmp(ts->m_loginName,m_curChatName) == 0 ) 
		{ 
			break; 
		} 
	} 
 
	if ( ts == g_AcceptClient.end() ) 
	{ 
		AfxMessageBox("对方已经下线!"); 
		return; 
	} 
 
	DWORD dwClientIP = inet_addr(ts->m_ClientIPAddr); 
 
	uPort = (((dwClientIP)>>24)&0x000000ff) + (((m_dwLocalIPAddr)>>24)&0x000000ff); 
} 
 
void CChatWidnowDlg::ProRecvData(char *RecvData,SOCKADDR_IN saddrClient) 
{ 
	char szFlag = *RecvData; 
	switch( (BYTE)szFlag ) 
	{ 
	case 0x81: 
		{ 
			char lpszHeader[NET_TRANSMIT_BUFFER]; 
			char lpszChatContent[NET_TRANSMIT_BUFFER]; 
			ChatDataInfo *chatDataInfo = (ChatDataInfo *)RecvData; 
			if ( chatDataInfo->m_serialNum == m_serialNum-1 ) 
				SetEvent(m_hSend); 
			 
			sprintf(lpszHeader,"%s:%s",chatDataInfo->m_clientName,chatDataInfo->m_curSysTimer); 
			sprintf(lpszChatContent,"%s",chatDataInfo->m_curChatData); 
			 
			ShowText(lpszHeader,lpszChatContent);  //// 
 
			AckInfo * ackInfo = new AckInfo; 
			ackInfo->m_szFlag = (char )0x88; 
			ackInfo->m_serialNum = chatDataInfo->m_serialNum; 
			 
			int isend = sendto(m_ChatServerSocket,(char*)ackInfo,NET_TRANSMIT_BUFFER,0,(struct sockaddr FAR *)&saddrClient,sizeof(SOCKADDR_IN)); 
			 
			if ( isend == SOCKET_ERROR ) 
			{ 
				TRACE("发送ACK失败!"); 
			} 
 
			delete ackInfo; 
			break; 
		} 
	case 0x88: 
		{ 
			AckInfo *ackInfo = ( AckInfo *)RecvData; 
			if ( ackInfo->m_serialNum == m_serialNum-1 ) 
			{ 
				SetEvent(m_hSend); 
			} 
			break; 
		} 
	default: 
		break; 
	} 
 
} 
 
void CChatWidnowDlg::ShowText(char *lpszNT, char *lpszMsg) 
{  
	if ( m_bDFirst == TRUE ) 
	{ 
		m_ClientInfoLB = m_ClientInfoLB  + lpszNT; 
		m_bDFirst = FALSE ; 
	} 
	else if ( m_bNet == TRUE ) 
	{ 
		m_ClientInfoLB = m_ClientInfoLB  + lpszNT; 
		m_bNet = FALSE; 
	} 
	else if ( m_bLFirst = TRUE ) 
	{ 
		m_ClientInfoLB = m_ClientInfoLB  + lpszNT; 
		m_bLFirst = FALSE; 
	} 
	else 
		m_ClientInfoLB = m_ClientInfoLB + "\r\n" + lpszNT; 
	GetDlgItem(IDC_EDIT2)->SetWindowText((LPCSTR)m_ClientInfoLB); 
	CEdit *pEdit; 
	pEdit=(CEdit *)GetDlgItem(IDC_EDIT2); 
	int i=pEdit->GetLineCount(); 
	pEdit->LineScroll(i,0); 
 
	m_ClientInfoLB = m_ClientInfoLB + "\r\n" + lpszMsg + "\r\n"; 
 
	GetDlgItem(IDC_EDIT2)->SetWindowText((LPCSTR)m_ClientInfoLB); 
	pEdit = (CEdit *) GetDlgItem(IDC_EDIT2); 
	i = pEdit->GetLineCount(); 
	pEdit->LineScroll(i,0); 
} 
 
void CChatWidnowDlg::GetLocalPort(unsigned short &usNetPort) 
{ 
	vector::iterator ts; 
	for ( ts = g_AcceptClient.begin(); ts != g_AcceptClient.end(); ts ++ ) 
	{ 
		if ( strcmp(ts->m_loginName,m_curChatName) == 0 ) 
		{ 
			break; 
		} 
	} 
	if ( ts == g_AcceptClient.end() ) 
	{ 
		AfxMessageBox("对方已经下线!"); 
		return ; 
	} 
	DWORD dwClientIP = inet_addr(ts->m_ClientIPAddr); 
	usNetPort = ((dwClientIP>>24)&0x000000ff) + ((m_dwLocalIPAddr>>24)&0x000000ff); 
} 
 
void CChatWidnowDlg::FastToClient() 
{ 
	if ( m_bLFirst == TRUE ) 
	{ 
		char lpszHeader[NET_TRANSMIT_BUFFER]; 
		char lpszChatContent[NET_TRANSMIT_BUFFER]; 
		SYSTEMTIME sysTimer; 
		GetLocalTime(&sysTimer); 
		ChatDataInfo *ChatInfo = new ChatDataInfo; 
		ChatInfo->m_szFlag = (char )0x81; 
		ChatInfo->m_serialNum = m_serialNum ++ ; 
		sprintf(ChatInfo->m_clientName,"%s",m_szMyLocalName); 
 
 
		sprintf(ChatInfo->m_curSysTimer,"%u-%u-%u %u:%2u:%2u", 
			sysTimer.wYear, 
			sysTimer.wMonth, 
			sysTimer.wDay, 
			sysTimer.wHour, 
			sysTimer.wMinute, 
			sysTimer.wSecond 
			); 
		sprintf(ChatInfo->m_curChatData,"%s",m_firstContent); 
		sprintf(lpszHeader,"%s:%s",ChatInfo->m_clientName,ChatInfo->m_curSysTimer); 
		sprintf(lpszChatContent,"%s",ChatInfo->m_curChatData); 
		ShowText(lpszHeader,lpszChatContent);///// 
		SendQueryChatCommand((char*)ChatInfo); 
		 
		delete ChatInfo; 
	} 
}