VC++:汉王人脸通SDK示例代码(二)接收卡点数据

同系列文章:

运行环境

下载安装Visual C++ Redistributable for Visual Studio 2015

演示程序源代码下载:

FaceIdDemo-VC2015-20161118.zip
注意:请将FaceId.dll和FaceId.lib拷贝到Release和Debug目录下

演示程序界面:
TcpServerDemo-VC

示例代码
TcpServerDemoDlg.h


// TcpServerDemoDlg.h : 头文件
//

#pragma once

#include "..\\FaceId\\Source\\TcpListenerPlus.h"

// CTcpServerDemoDlg 对话框
class CTcpServerDemoDlg : public CDialogEx, IServerSocketHandler
{
// 构造
public:
	CTcpServerDemoDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
	enum { IDD = IDD_TCPSERVERDEMO_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButtonstart();
	afx_msg void OnBnClickedButtonclear();
	afx_msg void OnDestroy();
	afx_msg void OnBnClickedButtonsetserver();

private:
	// IServerSocketHandler接口实现
	BOOL IsTrustedIPAddress(const CHAR* IPAddress);
	DWORD OnServerTaskRequest(NetworkStreamPlus* Stream);

private:
	BOOL IsServerRunning = FALSE;	// 服务器是否已经运行
	TcpListenerPlus* TcpServer = NULL;		// 数据接收侦听器
	std::list<std::string>* TrustedIPAddresses = NULL;	// 可信IP地址列表

public:
	CString m_AttendRecords;

private:
	CONST UINT DeviceCodePage = 936;	// 设备通信字符集为简体中文
};

TcpServerDemoDlg.cpp

/* ----------------------------------------------------------
* 文件名称:TcpServerDemoDlg.cpp
*
* 作者:秦建辉
*
* QQ:36748897
*
* 博客:http://www.firstsolver.com/wordpress/
*
* 开发环境:
*      Visual Studio V2013
*
* 版本历史:
*	V1.0    2014年09月24日
*           VC:人脸通SDK示例代码-接收卡点数据
* ------------------------------------------------------------ */

// TcpServerDemoDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "TcpServerDemo.h"
#include "TcpServerDemoDlg.h"
#include "afxdialogex.h"
#include "..\\FaceId\\Source\\SocketUtils.h"
#include "..\\FaceId\\Source\\FaceId.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#ifdef _DEBUG
#pragma comment(lib, "..\\Debug\\FaceId.lib")
#else
#pragma comment(lib, "..\\Release\\FaceId.lib")
#endif

// CTcpServerDemoDlg 对话框



CTcpServerDemoDlg::CTcpServerDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CTcpServerDemoDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTcpServerDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CTcpServerDemoDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTONSTART, &CTcpServerDemoDlg::OnBnClickedButtonstart)
	ON_BN_CLICKED(IDC_BUTTONCLEAR, &CTcpServerDemoDlg::OnBnClickedButtonclear)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTONSETSERVER, &CTcpServerDemoDlg::OnBnClickedButtonsetserver)
END_MESSAGE_MAP()


// CTcpServerDemoDlg 消息处理程序

BOOL CTcpServerDemoDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// 设置参数
	SetDlgItemText(IDC_EDITDEVICEIP, TEXT("192.168.1.18"));	// 设置设备地址
	SetDlgItemInt(IDC_EDITDEVICEPORT, 9922, FALSE);	// 设备默认端口
	SetDlgItemInt(IDC_EDITSERVERPORT, 9900, FALSE);	// 服务器默认端口

	// 设置服务器地址
	std::list<SOCKADDR*> AddrList;
	if (StringToSockAddrSet(TEXT(""), 0, AddrList, AF_INET) == 0)
	{
		std::list<SOCKADDR*>::iterator first = AddrList.begin(), last = AddrList.end();
		TCHAR StringBuffer[64];
		CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBOSERVERIP);	// 注意设置Sort为FALSE
		while (first != last)
		{		
			if (SockAddrToIPString(*first, StringBuffer, _countof(StringBuffer)) == 0)
			{
				pComboBox->AddString(StringBuffer);
			}
			first++;
		}

		INT n = pComboBox->GetCount();
		if (n > 0)
		{	// 设置当前选择
			pComboBox->SetCurSel(0);

			// 如果一个IP,禁止选择
			if (n == 1) pComboBox->EnableWindow(FALSE);
		}

		// 释放内存
		first = AddrList.begin();
		while (first != last)
		{
			delete *first;
			first++;
		}
		AddrList.clear();
	}

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CTcpServerDemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CTcpServerDemoDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

// 启动或者关闭侦听
void CTcpServerDemoDlg::OnBnClickedButtonstart()
{
	if (IsServerRunning)
	{	// 释放侦听器
		if (TcpServer != NULL)
		{
			delete TcpServer;
			TcpServer = NULL;
		}

		IsServerRunning = FALSE;
		SetDlgItemText(IDC_BUTTONSTART, TEXT("开启侦听"));
	}
	else
	{	
		// 创建侦听服务器
		try
		{	
			TCHAR ServerIP[64];
			GetDlgItemText(IDC_COMBOSERVERIP, ServerIP, _countof(ServerIP));
			TcpServer = new TcpListenerPlus(ServerIP, GetDlgItemInt(IDC_EDITSERVERPORT), AF_INET);
		}
		catch (DWORD dwErrorCode)
		{
			TCHAR Information[256];
			StringCchPrintf(Information, _countof(Information), TEXT("错误代码:%d"), dwErrorCode);
			MessageBox(Information, TEXT("错误"), MB_OK | MB_ICONERROR | MB_DEFBUTTON1);
			return;
		}

		//	设置通信密码
		TcpServer->SetSecretKey(NULL);	// 注意:通信密码要和设备一致

		// 开启侦听服务
		DWORD ErrorCode = TcpServer->StartListenThread(this, 0, MAXINT32, SOMAXCONN);
		if (ErrorCode == ERROR_SUCCESS)
		{
			IsServerRunning = TRUE;
			SetDlgItemText(IDC_BUTTONSTART, TEXT("关闭侦听"));
		}
		else
		{
			MessageBox(TEXT("启动侦听服务器失败!"), TEXT("错误"), MB_OK | MB_ICONERROR | MB_DEFBUTTON1);
			if (TcpServer != NULL)
			{
				delete TcpServer;
				TcpServer = NULL;
			}
		}
	}
}

// 清空文本框
void CTcpServerDemoDlg::OnBnClickedButtonclear()
{
	SetDlgItemText(IDC_EDITDATA, TEXT(""));
	m_AttendRecords = TEXT("");
}

// 窗口关闭
void CTcpServerDemoDlg::OnDestroy()
{
	CDialogEx::OnDestroy();

	// 释放监听器
	if (TcpServer != NULL)
	{
		delete TcpServer;
		TcpServer = NULL;
	}

	// 释放可信IP地址列表
	if (TrustedIPAddresses != NULL)
	{
		delete TrustedIPAddresses;
		TrustedIPAddresses = NULL;
	}
}

// 设置服务器地址
void CTcpServerDemoDlg::OnBnClickedButtonsetserver()
{
	// 连接设备
	FaceId* TcpClient = NULL;
	try
	{
		TCHAR DeviceIP[64];
		GetDlgItemText(IDC_EDITDEVICEIP, DeviceIP, _countof(DeviceIP));
		TcpClient = new FaceId(DeviceIP, GetDlgItemInt(IDC_EDITDEVICEPORT));
	}
	catch (DWORD dwErrorCode)
	{
		TCHAR Information[256];
		StringCchPrintf(Information, _countof(Information), TEXT("错误代码:%d"), dwErrorCode);
		MessageBox(Information, TEXT("错误"), MB_OK | MB_ICONERROR | MB_DEFBUTTON1);
		return;
	}
	
	// 设置服务器
	TCHAR ServerIP[64];
	GetDlgItemText(IDC_COMBOSERVERIP, ServerIP, _countof(ServerIP));

	TCHAR Command[256];
	StringCchPrintf(Command, _countof(Command), TEXT("SetServerHost(ip=\"%s\" port=\"%d\")"), ServerIP, GetDlgItemInt(IDC_EDITSERVERPORT));

	tstring Answer;
	INT ReceivedChars = TcpClient->Execute(Command, Answer, DeviceCodePage);
	if (ReceivedChars > 0)
	{
		MessageBox(TEXT("设置服务器成功!"), TEXT("成功"), MB_OK | MB_ICONINFORMATION | MB_DEFBUTTON1);
	}
	else
	{
		StringCchPrintf(Command, _countof(Command), TEXT("设置服务器失败!错误代码=%d"), ReceivedChars);
		MessageBox(Command, TEXT("失败"), MB_OK | MB_ICONERROR | MB_DEFBUTTON1);
	}

	// 断开连接
	TcpClient->Close();
	delete TcpClient;
}

// 判断是否是可信的IP地址
BOOL CTcpServerDemoDlg::IsTrustedIPAddress(const CHAR* IPAddress)
{
	if (TrustedIPAddresses == NULL)
	{
		return TRUE;
	}
	else
	{
		std::list<std::string>::const_iterator Begin = TrustedIPAddresses->begin();
		std::list<std::string>::const_iterator End = TrustedIPAddresses->end();
		if (std::find(Begin, End, IPAddress) == End)
			return FALSE;
		else
			return TRUE;
	}
}

// 处理数据接收
DWORD CTcpServerDemoDlg::OnServerTaskRequest(NetworkStreamPlus* Stream)
{
	TCHAR Command[256];
	while (TRUE)
	{
		tstring Answer;
		INT WSAErrorCode = Stream->Read(Answer, DeviceCodePage);
		if (WSAErrorCode == 0) break;	// 连接已断开
		if (WSAErrorCode > 0)
		{
			m_AttendRecords.AppendFormat(TEXT("%s\r\n"), Answer.c_str());
			SetDlgItemText(IDC_EDITDATA, m_AttendRecords);

			if (Answer.compare(0, _tcslen(TEXT("PostRecord")), TEXT("PostRecord")) == 0)
			{	// 准备上传考勤记录
				StringCchPrintf(Command, _countof(Command), TEXT("Return(result=\"success\" postphoto=\"false\")"));
				Stream->Write(Command, DeviceCodePage);				
			}
			else if (Answer.compare(0, _tcslen(TEXT("PostEmployee")), TEXT("PostEmployee")) == 0)
			{	// 准备上传人员信息
				StringCchPrintf(Command, _countof(Command), TEXT("Return(result=\"success\")"));
				Stream->Write(Command, DeviceCodePage);
			}
			else if (Answer.compare(0, _tcslen(TEXT("Record")), TEXT("Record")) == 0)
			{	// 接收考勤记录
				StringCchPrintf(Command, _countof(Command), TEXT("Return(result=\"success\")"));
				Stream->Write(Command, DeviceCodePage);
			}
			else if (Answer.compare(0, _tcslen(TEXT("Employee")), TEXT("Employee")) == 0)
			{	// 接收人员信息
				StringCchPrintf(Command, _countof(Command), TEXT("Return(result=\"success\")"));
				Stream->Write(Command, DeviceCodePage);
			}
			else if (Answer.compare(0, _tcslen(TEXT("Quit")), TEXT("Quit")) == 0)
			{	// 连接断开
				break;
			}
		}
	}

	return ERROR_SUCCESS;
}

Comments are closed.