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

📄 tcpclientexdlg.cpp

📁 周立功WinCE光盘资料
💻 CPP
字号:
// TCPClientExDlg.cpp : implementation file
//

#include "stdafx.h"
#include "TCPClientEx.h"
#include "TCPClientExDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CTCPClientExDlg dialog

CTCPClientExDlg::CTCPClientExDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTCPClientExDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTCPClientExDlg)
	m_RemoteHost = _T("");
	m_RemotePort = 0;
	m_SendEdit = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTCPClientExDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTCPClientExDlg)
	DDX_Control(pDX, IDC_CREATE_CONNECT, m_ButCreConnect);
	DDX_Control(pDX, IDC_DISCONNECT, m_ButDisConnect);
	DDX_Text(pDX, IDC_REMOTEHOST, m_RemoteHost);
	DDX_Text(pDX, IDC_REMOTEPORT, m_RemotePort);
	DDX_Text(pDX, IDC_SEND_EDIT, m_SendEdit);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTCPClientExDlg, CDialog)
	//{{AFX_MSG_MAP(CTCPClientExDlg)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_CREATE_CONNECT, OnCreateConnect)
	ON_BN_CLICKED(IDC_CLEAR_RECDISP, OnClearRecdisp)
	ON_BN_CLICKED(IDC_SEND, OnSend)
	ON_BN_CLICKED(IDC_DISCONNECT, OnDisconnect)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTCPClientExDlg message handlers

BOOL CTCPClientExDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);					// Set big icon
	SetIcon(m_hIcon, FALSE);				// Set small icon
	CenterWindow(GetDesktopWindow());		// center to the hpc screen

	m_RemoteHost = "192.168.0.16";			/* 默认远程主机 IP 地址 */
	m_RemotePort = 1011;					/* 默认远程主机端口 */

	m_strRecDisp = _T("");					/* 清空接收区字符 */
	m_Socket = INVALID_SOCKET;				/* Socket 无效 */
	m_ExitThreadEvent = NULL;				/* TCP 接收线程退出事件无效 */
	m_ButDisConnect.EnableWindow(FALSE);	/* "断开连接" 按键无效 */
	UpdateData(FALSE);
	return TRUE;
}


/*******************************************************************************************
函数名称: CALLBACK CTCPClientExDlg::OnTcpRecv
描    述: TCP 接收数据成功回调函数
输入参数: 无
输出参数: 无
返    回: FALSE: 失败;    TRUE: 成功
********************************************************************************************/
void CALLBACK CTCPClientExDlg::OnTcpRecv(CWnd* pWnd, char *buf, int buflen)
{
	CString strTmp;

	CTCPClientExDlg * pDlg = (CTCPClientExDlg*)pWnd;
	CEdit *pRecvStrEdit = (CEdit*)pDlg->GetDlgItem(IDC_REC_DISP);
														/* 取得控件指针 */
	for (int i = 0; i < buflen; i++)
	{
		strTmp.Format(_T("%c"), *buf);
		pDlg->m_strRecDisp += strTmp;
		buf++;
	}

	pRecvStrEdit->SetWindowText(pDlg->m_strRecDisp);	/* 在窗口显示出来 */
}


/*******************************************************************************************
函数名称: CALLBACK CTCPClientExDlg::OnTcpError
描    述: TCP 错误回调函数
输入参数: 无
输出参数: 无
返    回: 无
********************************************************************************************/
void CALLBACK CTCPClientExDlg::OnTcpError(CWnd *pWnd, int nErrorCode)
{
	


}

/*******************************************************************************************
函数名称: CTCPClientExDlg::TCPRecvTread
描    述: TCP 接收线程
输入参数: LPVOID lparam: 线程参数,创建线程时传入
输出参数: 无
返    回: 0: 线程退出, 返回值没特殊含义
********************************************************************************************/
DWORD CTCPClientExDlg::TCPRecvTread(LPVOID lparam)
{
	fd_set fdRead;
	TIMEVAL aTime;
	int iErrorCode;
	int ret;
	aTime.tv_sec = 1;
	aTime.tv_usec = 0;
	CTCPClientExDlg *pDlg = (CTCPClientExDlg *)lparam;

	while(TRUE)
	{
		if (WaitForSingleObject(pDlg->m_ExitThreadEvent, 0) == WAIT_OBJECT_0)
			break;

		FD_ZERO(&fdRead);
		FD_SET(pDlg->m_Socket, &fdRead);
		ret = select(0, &fdRead, NULL, NULL, &aTime);
		if (ret == SOCKET_ERROR)
		{
			iErrorCode = WSAGetLastError();
			pDlg->OnTcpError(pDlg, iErrorCode);
			break;
		}

		if (ret > 0)
		{
			if (FD_ISSET(pDlg->m_Socket, &fdRead))			/* 检查该socket是否是fdRead中的一员 */
			{
				char *recvBuf = new char[1024];
				// 接收数据
				int recvlen = recv(pDlg->m_Socket, recvBuf, 1024, 0);	
				if ((recvlen == SOCKET_ERROR) || (recvlen == 0))
				{
					iErrorCode = WSAGetLastError();
					pDlg->OnTcpError(pDlg, iErrorCode);
					delete[] recvBuf;
					break;
				}
				else 
				{		
					pDlg->OnTcpRecv(pDlg, recvBuf, recvlen); /* 正确接收回调函数 */
					delete[] recvBuf;
				}

			}// end of if (FD_ISSET(pDlg->m_Socket, &fdRead))

		}// end of if (ret > 0)
		
	}// end of while(TRUE)

	return 0;
}



/*******************************************************************************************
函数名称: CTCPClientExDlg::OnCreateConnect
描    述: "创建连接" 按键单击事件代码
输入参数: 无
输出参数: 无
返    回: 无
********************************************************************************************/
void CTCPClientExDlg::OnCreateConnect() 
{
	WSADATA wsa;
	DWORD IDThread;

	if (WSAStartup(MAKEWORD(1,1), &wsa) != 0)					/* WinSock 初始化 */
	{
		MessageBox(_T("加载套接字失败!"));
		return;
	}

	m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);		/* 创建TCP套接字 */
	if (m_Socket == INVALID_SOCKET)
	{
		WSACleanup();
		MessageBox(_T("创建套接字失败!"));	
		return;
	}

	UpdateData(TRUE);
	
	// 初始化远程 IP 地址及端口
	m_RemoteAddr.sin_family = AF_INET; 						
	m_RemoteAddr.sin_port = htons(m_RemotePort);				/* 远程端口地址 */

	char charRemoteHost[255];
	ZeroMemory(charRemoteHost, 255);
	int len = m_RemoteHost.GetLength(); 
	if (len > 255)
	{
		MessageBox(_T("输入远程IP长度超长!"));
		return;		
	}

	// 将 Unicode 字符串转换为字节
	LPTSTR pStr = m_RemoteHost.GetBuffer(len);
	WideCharToMultiByte(CP_ACP, 0, pStr, len, charRemoteHost, len, NULL, NULL);

	DWORD ipaddress = inet_addr(charRemoteHost);				/* 远程 IP 地址 */
 	if ((INADDR_NONE == ipaddress) || (0 == ipaddress))
	{
		MessageBox(_T("输入远程IP地址格式不正确!"));
		return;
	}
	m_RemoteAddr.sin_addr.s_addr = ipaddress;

	// 连接远程TCP服务器
	int ret = connect(m_Socket, (struct sockaddr *)&m_RemoteAddr, sizeof(m_RemoteAddr));
	if (ret == SOCKET_ERROR)
	{
		MessageBox(_T("连接TCP服务器失败!"));
		return;
	}

	DWORD ul = 1;
	ioctlsocket(m_Socket, FIONBIO, &ul);						/* 设置通信模式为异步模式 */

	m_ExitThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);	/* 创建 TCP 接收线程退出事件 */
	// 创建 TCP 接收线程
	HANDLE hRecvThread = CreateThread(0, 0, TCPRecvTread, this, 0, &IDThread);
	if (hRecvThread == NULL) 
	{
		closesocket(m_Socket);
		MessageBox(_T("创建TCP接收线程失败!"));
	}
	CloseHandle(hRecvThread);									/* 关闭接收线程句柄 */

	m_ButDisConnect.EnableWindow(TRUE);
	m_ButCreConnect.EnableWindow(FALSE);
}



/*******************************************************************************************
函数名称: CTCPClientExDlg::OnDisconnect
描    述: "断开连接" 按键单击事件代码, 断开与远程TCP服务器的连接
输入参数: 无
输出参数: 无
返    回: 无
********************************************************************************************/
void CTCPClientExDlg::OnDisconnect() 
{
	if (m_ExitThreadEvent != NULL)
	{
		SetEvent(m_ExitThreadEvent);					/* 设置接收线程退出事件, 通知线程退出 */
		Sleep(1000);
		CloseHandle(m_ExitThreadEvent);					/* 关闭线程退出事件句柄 */
	}

	if (m_Socket != INVALID_SOCKET)
	{	
		if (closesocket(m_Socket) == SOCKET_ERROR)		/* 关闭 Socket */	
		{
			MessageBox(_T("关闭Socket失败!"));
			return;
		}
		m_Socket = INVALID_SOCKET;

		if (WSACleanup() == SOCKET_ERROR)				/* 释放Socket资源*/
			MessageBox(_T("释放Socket资源失败!"));
	}

	m_ButDisConnect.EnableWindow(FALSE);				/* 禁止"断开连接"按键 */
	m_ButCreConnect.EnableWindow(TRUE);					/* 使能"创建连接"按键 */
}



/*******************************************************************************************
函数名称: CTCPClientExDlg::OnSend
描    述: "发送" 按键单击事件代码
输入参数: 无
输出参数: 无
返    回: 无
********************************************************************************************/
void CTCPClientExDlg::OnSend() 
{
	int nErrorCode;
	int cnt = 0, actlen = 0;

	if (m_Socket == NULL)
		return;

	UpdateData(TRUE);
 	int sendlen = m_SendEdit.GetLength();				 /* 取得输入字符串长度 */
	char *psendbuff = new char[sendlen];

	for(int i = 0; i < sendlen;i++)
		psendbuff[i] = (char)m_SendEdit.GetAt(i);		 /* 转换为单字节字符 */
	
	while(cnt < sendlen)
	{	// 发送数据
		actlen = send(m_Socket, psendbuff + cnt, sendlen - cnt, 0);
		if (actlen == SOCKET_ERROR )
		{
			MessageBox(_T("TCP 数据发送失败!"));
			nErrorCode = WSAGetLastError();
			delete[] psendbuff;
			return;
		}

		cnt = cnt + actlen;
		if (cnt < sendlen)
			Sleep(1000);
	}
	
	delete[] psendbuff;
}



/*******************************************************************************************
函数名称: CTCPClientExDlg::OnClearRecdisp
描    述: "清除接收区" 按键单击事件代码
输入参数: 无
输出参数: 无
返    回: 无
********************************************************************************************/
void CTCPClientExDlg::OnClearRecdisp() 
{
	m_strRecDisp = _T("");
	CEdit *pRecDispEdit = (CEdit*)GetDlgItem(IDC_REC_DISP); /* 取得控件指针 */
														
	pRecDispEdit->SetWindowText(m_strRecDisp);				/* 在窗口显示出来 */
}



/*******************************************************************************************
函数名称: CTCPClientExDlg::OnDestroy
描    述: 对话框关闭事件处理函数
输入参数: 无
输出参数: 无
返    回: 无
********************************************************************************************/
void CTCPClientExDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	OnDisconnect();											/* 断开连接 */
}

⌨️ 快捷键说明

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