www.pudn.com > DNC.rar > MySocket.cpp


// MySocket.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "NC.h" 
#include "MySocket.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CMySocket dialog 
 
#define FLAG		2 
#define SIZEFILE	1024 
 
 
//SOCK_TCP 
 
CWinThread	*pThreadSendFile;	//发送文件线程-->_SendFileThread 
CWinThread	*pThreadSendMsg;		//发送消息线程 
CWinThread	*pThreadLisen;		//监听线程-->_ListenTcpThread 
CWinThread	*pReceiveThread;		//接受线程-->_ReceiveThread 
 
CMySocket::CMySocket(CWnd* pParent /*=NULL*/) 
	: CDialog(CMySocket::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CMySocket) 
	m_MsgSend = _T(""); 
	m_port = 1234; 
	//}}AFX_DATA_INIT 
	m_WorkType=0;//两者 
	m_client=1; 
	m_server=2; 
	FileWork=false; 
	FileStop=false; 
	StopServer=false; 
} 
 
 
void CMySocket::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CMySocket) 
	DDX_Control(pDX, IDC_LIST_BOX_ADDMSG, m_AddMsgLIst); 
	DDX_Control(pDX, IDC_PROGRESS_SEND_FILE, m_Progress); 
	DDX_Control(pDX, IDC_IPADDRESS, m_You_IP); 
	DDX_Text(pDX, IDC_EDIT_SENDMSG, m_MsgSend); 
	DDX_Text(pDX, IDC_PORT, m_port); 
	//}}AFX_DATA_MAP 
} 
 
 
BEGIN_MESSAGE_MAP(CMySocket, CDialog) 
	//{{AFX_MSG_MAP(CMySocket) 
	ON_BN_CLICKED(IDC_BUTTON_CONNECT, OnButtonConnect) 
	ON_BN_CLICKED(IDC_BUTTON_DISCONNECT, OnButtonDisconnect) 
	ON_BN_CLICKED(IDC_BUTTON_SEND_MSG, OnButtonSendMsg) 
	ON_BN_CLICKED(IDC_BUTTON_SEND_FILE, OnButtonSendFile) 
	ON_BN_CLICKED(IDC_BUTTON_STOP_FILE, OnButtonStopFile) 
	ON_BN_CLICKED(IDC_BUTTON_CLEAR, OnButtonClear) 
	ON_MESSAGE(WM_KSEND,OnKSend) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CMySocket message handlers 
 
BOOL CMySocket::OnInitDialog()  
{ 
	CDialog::OnInitDialog(); 
	 
	// TODO: Add extra initialization here 
	CString strLocalName; 
	GetLocalHostName(strLocalName); 
	CString strLocalIP; 
	GetIpAddress(strLocalName,strLocalIP); 
	m_You_IP.SetWindowText(strLocalIP);	//设置默认IP为本机 
	///////////////////////////////////////////////////////// 
	GetDlgItem(IDC_BUTTON_SEND_MSG)->EnableWindow(false);//发送消息不可用 
	GetDlgItem(IDC_BUTTON_SEND_FILE)->EnableWindow(false);//发送文件不可用 
	GetDlgItem(IDC_BUTTON_CLEAR)->EnableWindow(false);//清除不可用 
	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false);//断开连接不可用 
	GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE); 
 
	return TRUE;  // return TRUE unless you set the focus to a control 
	              // EXCEPTION: OCX Property Pages should return FALSE 
} 
CString CMySocket::GetError(DWORD error)	//返回错误信息 
{ 
	CString strError; 
	switch(error) 
	{ 
	case WSANOTINITIALISED: 
		strError="初始化错误"; 
		break; 
	case WSAENOTCONN: 
		strError="对方没有启动"; 
		break; 
	case WSAEWOULDBLOCK : 
		strError="对方已经关闭"; 
		break; 
	case WSAECONNREFUSED: 
		strError="连接的尝试被拒绝"; 
		break; 
	case WSAENOTSOCK: 
		strError="在一个非套接字上尝试了一个操作"; 
		break; 
	case WSAEADDRINUSE: 
		strError="特定的地址已在使用中"; 
		break; 
	case WSAECONNRESET: 
		strError="与主机的连接被关闭"; 
		break; 
	default: 
		strError="一般错误";	 
	} 
	return strError; 
	 
} 
 
int CMySocket::GetLocalHostName(CString &sHostName)	//获得本地计算机名称 
{ 
	char szHostName[256]; 
	int nRetCode; 
	nRetCode=gethostname(szHostName,sizeof(szHostName)); 
	if(nRetCode!=0) 
	{ 
		//产生错误 
		sHostName=_T("没有取得"); 
		return GetLastError(); 
	} 
	sHostName=szHostName; 
	return 0; 
} 
 
int CMySocket::GetIpAddress(const CString &sHostName, CString &sIpAddress)//获得本地IP 
{ 
	struct hostent FAR * lpHostEnt=gethostbyname(sHostName); 
	if(lpHostEnt==NULL) 
	{ 
		//产生错误 
		sIpAddress=_T(""); 
		return GetLastError(); 
	} 
	//获取IP 
	LPSTR lpAddr=lpHostEnt->h_addr_list[0]; 
	if(lpAddr) 
	{ 
		struct in_addr inAddr; 
		memmove(&inAddr,lpAddr,4); 
		//转换为标准格式 
		sIpAddress=inet_ntoa(inAddr); 
		if(sIpAddress.IsEmpty()) 
			sIpAddress=_T("没有取得"); 
	} 
	return 0; 
} 
int CMySocket::GetNamebyAddress(const CString &IpAddress,CString &sYouName)//获得对方计算机名称 
{ 
	unsigned long addr; 
	addr=inet_addr(IpAddress); 
	struct hostent FAR * lpHostEnt=gethostbyaddr((char *)&addr,4,AF_INET); 
	if(lpHostEnt==NULL) 
	{ 
		//产生错误 
		sYouName=_T(""); 
 
		AfxMessageBox("连接不上");//应该取得其错误 
		return -1; 
	} 
	CString name=lpHostEnt->h_name; 
	sYouName=name; 
	return 0; 
 
} 
//////////////////////////////////服务器线程开始/////////////////////////////////////////// 
 
//TCP监听线程 
UINT _ListenTcpThread(LPVOID lparam) 
{ 
	CMySocket *pDlg=(CMySocket *)lparam; 
	if(pDlg->StopServer==true)	return -1; 
	 
	CSocket sockSrvr; 
	pDlg->m_Potr=pDlg->m_port+pDlg->m_server;//保存当前使用端口,用于关闭 
	int createSucceed=sockSrvr.Create(pDlg->m_Potr); 
	if(createSucceed==0) 
	{ 
		AfxMessageBox("_ListenTcpThread Create错误!"+pDlg->GetError(GetLastError())); 
		return -1; 
	} 
	 
	int listenSucceed=sockSrvr.Listen();	//开始监听 
	if(listenSucceed==0) 
	{ 
		AfxMessageBox("_ListenTcpThread Listen错误!"+pDlg->GetError(GetLastError())); 
		return -1; 
	} 
	 
	CSocket recSo; 
	SOCKADDR_IN client; 
	int iAddrSize=sizeof(client); 
	 
	int acceptSucceed=sockSrvr.Accept(recSo,(SOCKADDR *)&client,&iAddrSize);	//接受连接并取得对方IP 
	if(acceptSucceed==0) 
	{ 
		AfxMessageBox("_ListenTcpThread Accept错误!"+pDlg->GetError(GetLastError())); 
		return -1; 
	} 
	sockSrvr.Close(); 
	char flag[FLAG]={0};		 
	if(recSo.Receive(flag,FLAG)!=2)  
	{ 
		return -1;	 
	} 
	pDlg->m_type=flag[0]; 
	if(pDlg->m_type=='D') return 0; 
	 
	pThreadLisen=::AfxBeginThread(_ListenTcpThread,pDlg); 
	pDlg->ReceiveFileMsg(recSo,client); 
	return 0; 
	 
} 
 
 
////////////////////////////////////服务器线程结束////////////////////////////////////// 
 
 
////////////////////////////////////客户端线程开始////////////////////////////////////// 
 
//发送文件线程 
UINT _SendFileThread(LPVOID lparam) 
{ 
	 
	CMySocket *pDlg=(CMySocket *)lparam; 
	if(pDlg->StopServer==true)	return -1; 
	 
	CSocket sockClient; 
	sockClient.Create(); 
	CString ip; 
	pDlg->m_You_IP.GetWindowText(ip); 
	 
	sockClient.Connect(ip, pDlg->m_port+pDlg->m_client);  
	//首先发送标记F为文件,2 
	int end=0; 
	end=sockClient.Send("F",FLAG); 
	///////////////////////////////////////////////////////////////////发送标志是否成功 
	if(end==SOCKET_ERROR)										 
	{ 
		AfxMessageBox("_SendFileThread Send错误!"+pDlg->GetError(GetLastError())); 
		return -1; 
	} 
	 
	else if(end!=2)  
	{ 
		AfxMessageBox("文件头错误"); 
		return -1; 
	} 
	/////////////////////////////////////////////////////////////////// 
	CFile myFile; 
	FILEINFO myFileInfo; 
	if(!myFile.Open(pDlg->m_fileName, CFile::modeRead | CFile::typeBinary)) 
		return -1; 
	myFileInfo.fileLength=myFile.GetLength();		//得到文件大小 
	strcpy(myFileInfo.fileName,myFile.GetFileName());//得到文件名称 
	 
	sockClient.Send(&myFileInfo,sizeof(myFileInfo));	//发送文件信息 
	 
	pDlg->m_Progress.SetRange32(0,myFileInfo.fileLength); 
	 
	myFile.Seek(0,CFile::begin); 
	char m_buf[SIZEFILE]={0}; 
	CString strError; 
	int num=0; 
	end=0; 
	int temp=0; 
	pDlg->GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(true); 
	 
	for(;;) 
	{ 
		if(pDlg->FileWork==false) 
		{ 
			pDlg->FileWork=true; 
			pDlg->GetDlgItem(IDCANCEL)->EnableWindow(false); 
			pDlg->GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false); 
		} 
		num=myFile.Read(m_buf, SIZEFILE); 
		if(num==0) break; 
		end=sockClient.Send(m_buf, num);  
		temp+=end; 
		pDlg->m_Progress.SetPos(temp); 
		if(pDlg->FileStop==true)  
		{ 
			pDlg->FileStop=false; 
			pDlg->FileWork=false; 
			break; 
		} 
		 
		if(end==SOCKET_ERROR) 
		{ 
			AfxMessageBox("_SendFileThread Send错误!"+pDlg->GetError(GetLastError())); 
			break; 
			 
		} 
	} 
	pDlg->m_Progress.SetPos(0); 
	CString strLocalName; 
	pDlg->GetLocalHostName(strLocalName); 
	CString strLocalIP; 
	pDlg->GetIpAddress(strLocalName,strLocalIP); 
	if(temp==myFileInfo.fileLength) 
		pDlg->AddMsgList(strLocalIP+"->"+strLocalName,"文件发送成功"); 
	else  
		pDlg->AddMsgList(strLocalIP+"->"+strLocalName,"文件发送失败"); 
	myFile.Close(); 
	sockClient.Close(); 
	pDlg->FileWork=false; 
	pDlg->GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE); 
	pDlg->GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(false); 
 
	pDlg->GetDlgItem(IDCANCEL)->EnableWindow(true); 
	pDlg->GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true); 
	 
	return 0; 
} 
 
 
 
UINT _SendMsgThread(LPVOID lparam)	//TCP发送信息线程 
{ 
	 
	CMySocket *pDlg=(CMySocket *)lparam; 
	if(pDlg->StopServer==true)	return -1; 
	 
	CSocket sockClient; 
	sockClient.Create(); 
	CString ip,strError; 
	pDlg->m_You_IP.GetWindowText(ip); 
	int conn=sockClient.Connect(ip, pDlg->m_port+pDlg->m_client); 
	if(conn==0)	/////////////////////////////////// 
	{ 
		AfxMessageBox("_SendMsgThread Connect错误!"+pDlg->GetError(GetLastError())); 
		sockClient.ShutDown(2); 
		sockClient.Close(); 
		AfxEndThread(1L); 
		return 0; 
		 
	} 
	//首先发送标记M为信息,2 
	int end=0; 
	end=sockClient.Send("M",FLAG);  
	if(end==SOCKET_ERROR) 
	{ 
		AfxMessageBox("_SendMsgThread Send错误!"+pDlg->GetError(GetLastError())); 
		return -1; 
	} 
	else if(end!=2) 
	{ 
		AfxMessageBox("消息头错误"); 
		return -1; 
	} 
	CString strMsg=pDlg->m_MsgSend; 
	end=sockClient.Send(strMsg,strMsg.GetLength());  
	if(end==SOCKET_ERROR) 
	{ 
		AfxMessageBox("_SendMsgThread Send错误!"+pDlg->GetError(GetLastError())); 
		return -1; 
	} 
	CString strLocalName; 
	pDlg->GetLocalHostName(strLocalName); 
	CString strLocalIP; 
	pDlg->GetIpAddress(strLocalName,strLocalIP); 
	pDlg->AddMsgList(strLocalIP+"->"+strLocalName,strMsg); 
	 
	int i=0; 
	sockClient.Close(); 
 
	return 0; 
} 
 
/////////////////////////////////////////////////////////////////// 
////////////////////////////////////客户端线程结束////////////////////////////////////// 
 
///////////////////////////////////函数////////////////////////////////////////// 
 
int CMySocket::ReceiveFileMsg(CSocket &recSo,SOCKADDR_IN &client)//接受函数 
{ 
 if(m_type=='F')			//文件 
	{ 
		SaveYouFile(recSo,client); 
	} 
	 
	else if(m_type=='M')	//信息 
	{ 
		char buff[100]={0}; 
		CString msg; 
		int ret=0; 
		for(;;) 
		{ 
			ret=recSo.Receive(buff,100); 
			if(ret==0) 
				break; 
			msg+=buff; 
		} 
		CString strOut,strIn; 
		m_You_IP.GetWindowText(strIn); 
		GetNamebyAddress(strIn,strOut); 
		CString youName; 
		youName.Format(inet_ntoa(client.sin_addr)); 
		CString str=youName+"<-"+strOut; 
		AddMsgList(str,msg); 
	} 
	recSo.Close();	 
	return 0; 
} 
 
int CMySocket::SaveYouFile(CSocket &recSo, SOCKADDR_IN &client)//接受文件 
{ 
	CString fname; 
	CFileDialog dlg(false);	//另存文件 
	FILEINFO myFileInfo; 
	recSo.Receive(&myFileInfo,sizeof(FILEINFO)); 
	int fileLength=myFileInfo.fileLength; 
	CString strfileIp,strfileName,strfileLength; 
	strfileIp.Format(inet_ntoa(client.sin_addr)); 
	strfileName.Format(myFileInfo.fileName); 
	strfileLength.Format("%f",myFileInfo.fileLength/1024.0); 
	CString title="文件"+strfileName+" 大小"+strfileLength+"KB "+"来在"+strfileIp+" 是否接受"; 
	dlg.m_ofn.lpstrTitle=title;//标题条 
	char fileme[500]={0};//必须足够大小 
	strcpy(fileme,strfileIp+strfileName); 
	dlg.m_ofn.lpstrFile=fileme;	//文件名称 
	if(dlg.DoModal()==IDOK) 
	{ 
		fname=dlg.GetPathName();	//得到文件名名称、路径 
		GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_SHOW); 
	} 
	else 
	{ 
		GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE); 
		GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(false); 
		 
		GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true); 
		GetDlgItem(IDCANCEL)->EnableWindow(true); 
		 
		recSo.Close();	 
		return 0;	 
		 
	} 
	char buf[SIZEFILE]={0}; 
	CFile f(fname,CFile::modeCreate|CFile::modeWrite);	//存文件 
	 
	m_Progress.SetRange32(0,fileLength); 
	 
	int n=0;	//接受的字节数 0表示结束 
	int temp=0; 
	GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(true); 
	 
	GetDlgItem(IDCANCEL)->EnableWindow(false); 
	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false); 
	 
	 
	for(;;) 
	{ 
		n=recSo.Receive(buf,SIZEFILE);	//接受 
		if(n==0)		//0表示结束 
			break;		//接受完毕 
		f.Write(buf,n); 
		temp+=n; 
		m_Progress.SetPos(temp); 
		if(FileWork==false) FileWork=true; 
		if(FileStop==true)  
		{ 
			FileStop=false; 
			FileWork=false; 
			break ; 
		} 
		 
	} 
	f.Close(); 
	m_Progress.SetPos(0); 
	if(temp==fileLength) 
		AddMsgList(inet_ntoa(client.sin_addr),"文件接受成功"); 
	else 
		AddMsgList(inet_ntoa(client.sin_addr),"文件接受失败"); 
	FileWork=false; 
	GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE); 
	GetDlgItem(IDC_BUTTON_STOP_FILE)->EnableWindow(false); 
	 
	GetDlgItem(IDCANCEL)->EnableWindow(true); 
	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true); 
	return 0; 
} 
void CMySocket::AddMsgList(CString IP,CString str) //添加信息于LISTBOX 控件中 
{ 
	SYSTEMTIME tm; 
	GetLocalTime(&tm); 
	CString time; 
	time.Format(_T(" %d:%02.2d"), tm.wHour, tm.wMinute); 
	m_AddMsgLIst.AddString(IP+"于"+time+"说道: "+str); 
	int numList=m_AddMsgLIst.GetCount()-1; 
	GetDlgItem(IDC_BUTTON_CLEAR)->EnableWindow(true); 
	m_AddMsgLIst.SetTopIndex(numList); 
	m_AddMsgLIst.SetCurSel(numList); 
	//水平滚动 
	int max_width=0; 
	CSize sz; 
	CClientDC dc(this); 
	for(int i=0;iEnableWindow(true);//连接可用 
		return; 
	} 
	m_MsgSend="你好!和"+strIn+"连接成功!"; 
 
 
	// 
	pThreadLisen=::AfxBeginThread(_ListenTcpThread,this);	//开始TCP线程 
	GetDlgItem(IDC_BUTTON_SEND_MSG)->EnableWindow(true);//发送消息可用 
	GetDlgItem(IDC_BUTTON_SEND_FILE)->EnableWindow(true);//文件可用 
		 
	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);//断开可用 
	GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(false);//连接不可用 
	GetDlgItem(IDC_IPADDRESS)->EnableWindow(false); 
 
		UpdateData(false); 
	 
} 
 
void CMySocket::OnButtonDisconnect()  
{ 
    GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(true); 
	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false); 
	GetDlgItem(IDC_BUTTON_SEND_MSG)->EnableWindow(false); 
	GetDlgItem(IDC_BUTTON_SEND_FILE)->EnableWindow(false); 
	m_AddMsgLIst.ResetContent(); 
	GetDlgItem(IDC_BUTTON_CLEAR)->EnableWindow(false); 
	GetDlgItem(IDC_IPADDRESS)->EnableWindow(true); 
	m_AddMsgLIst.SendMessage(LB_SETHORIZONTALEXTENT,0,0); 
 
/////////////////////////////////////////发送结束 
    DWORD   dwStatus; 
		if (pThreadLisen != NULL) 
		{ 
			if(::GetExitCodeThread(pThreadLisen->m_hThread, &dwStatus)==0) 
			{ 
				int errror=GetLastError(); 
				return; 
			} 
			if (dwStatus == STILL_ACTIVE) 
			{ 
				CSocket sockClient; 
				sockClient.Create(); 
				CString ip,strError; 
				ip="127.0.0.1"; 
				int conn=sockClient.Connect(ip, m_Potr); 
				if(conn==0)	/////////////////////////////////// 
				{ 
					AfxMessageBox("关闭错误!"+GetError(GetLastError())); 
					sockClient.ShutDown(2); 
					sockClient.Close(); 
					return; 
					 
				} 
				sockClient.Send("D",FLAG); //结束 
				 
			} 
			else 
			{ 
				delete pThreadLisen; 
				pThreadLisen = NULL; 
			} 
		} 
	 
} 
 
void CMySocket::OnButtonSendMsg()  
{ 
    UpdateData(true); 
	if(m_MsgSend.GetLength()==0) return; 
	::AfxBeginThread(_SendMsgThread,this); 
	 
} 
 
void CMySocket::OnButtonSendFile()  
{ 
    CFileDialog dlg(true); 
	CString ip; 
	m_You_IP.GetWindowText(ip); 
	CString title="文件发往"+ip+"请选择"; 
	dlg.m_ofn.lpstrTitle=title;//标题条 
	if(dlg.DoModal()==IDOK) 
	{ 
		m_fileName=dlg.GetPathName(); 
		GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_SHOW); 
		pThreadSendFile=::AfxBeginThread(_SendFileThread,this);	//开始传送文件线程 
	} 
	 
} 
 
void CMySocket::OnButtonStopFile()  
{ 
    FileStop=true; 
	FileWork=false; 
	GetDlgItem(IDCANCEL)->EnableWindow(true); 
	GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);	 
} 
 
void CMySocket::OnButtonClear()  
{ 
    m_AddMsgLIst.ResetContent(); 
	GetDlgItem(IDC_BUTTON_CLEAR)->EnableWindow(false); 
	m_AddMsgLIst.SendMessage(LB_SETHORIZONTALEXTENT,0,0); 
	 
} 
LRESULT CMySocket::OnKSend(WPARAM wParam,LPARAM lParam) 
{ 
	OnButtonSendMsg(); 
	return 0; 
} 
 
BOOL CMySocket::PreTranslateMessage(MSG* pMsg)  
{ 
if (pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN) 
		 
		if(GetFocus()->GetDlgCtrlID()==IDC_EDIT_SENDMSG ||GetFocus()->GetDlgCtrlID()==IDC_BUTTON_SEND_MSG) 
		{ 
			AfxGetMainWnd()->SendMessage(WM_KSEND); 
			return TRUE; 
		} 
	 
	return CDialog::PreTranslateMessage(pMsg); 
}