在C++Builder中调用hp-socket函数库方法如下:
(1)从hp-socket-5.4.4目录中复制出DLL和lib,路径如下:
hp-socket-5.4.4\hp-socket-5.4.4\Windows\Bin\HPSocket4C\x86\HPSocket4C.dll
hp-socket-5.4.4\hp-socket-5.4.4\Windows\Bin\HPSocket4C\x86\HPSocket4C.lib
(2)利用C++Builder提供的工具,将VC版的导入库转为C++Builder支持的导入库.如下:
coff2omf -lib:ms c:/HPSocket4C.lib bcb c:/HPSocket4CB.lib
(3)包含HPSokcet4C.h头文件,文件所在路径如下:
hp-socket-5.4.4\hp-socket-5.4.4\Windows\Src
只能以函数的方式调用HPSocket4C.dll中的功能,虽然作者提供了一个类,但是由于兼容性,编译不能通过.
#include "HPSocket4C.h"
#include "globalUnit.h"
#include <Forms.hpp>
#pragma comment(lib,HPSocket4CB.lib)
class TGpsServer
{
public:
static HWND m_hWnd;
char m_szIP[20];
int PORT;
TGpsServer();
~TGpsServer();
HP_TcpPullServer m_pServer; //创建服务器
HP_TcpPullServerListener m_pListener;//监听器
private:
//回调函数
static En_HP_HandleResult __stdcall OnPrepareListen(HP_Server pSender, unsigned int soListen);
static En_HP_HandleResult __stdcall OnAccept(HP_Server pSender, HP_CONNID dwConnID, unsigned int soClient);
static En_HP_HandleResult __stdcall OnSend(HP_Server pSender, HP_CONNID dwConnID,const BYTE* pData, int iLength);
static En_HP_HandleResult __stdcall OnReceive(HP_Server pSender, HP_CONNID dwConnID, int iLength);
static En_HP_HandleResult __stdcall OnClose(HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode);
static En_HP_HandleResult __stdcall OnShutdown(HP_Server pSender);
public:
VOID StartServer(HWND hWnd);
VOID StopServer();
static STExtraData* FindExtraData(HP_Server pSender, HP_CONNID dwConnID);
static void RemoveExtraData(HP_Server pSender, HP_CONNID dwConnID);
private:
static BOOL m_ServerStart;
};
//静态成员变量初始化
BOOL TGpsServer::m_ServerStart = FALSE;
HWND TGpsServer::m_hWnd = NULL;
#endif
以上是自定义类的.h文件(其中STExtraData为自定义的结构体,用来传递附加数据).cpp文件内容如下:
#pragma hdrstop
#include "HpSocketUnit.h"
#include <stdio.h>
#include <utilcls.h>
#include <assert.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
TGpsServer::TGpsServer()
{
// 创建监听器对象
m_pListener = ::Create_HP_TcpPullServerListener();
// 创建 Socket 对象
m_pServer = ::Create_HP_TcpPullServer(m_pListener);
// 设置 Socket 监听器回调函数
::HP_Set_FN_Server_OnPrepareListen(m_pListener, OnPrepareListen);
::HP_Set_FN_Server_OnAccept(m_pListener, OnAccept);
::HP_Set_FN_Server_OnSend(m_pListener, OnSend);
::HP_Set_FN_Server_OnPullReceive(m_pListener, OnReceive);
::HP_Set_FN_Server_OnClose(m_pListener, OnClose);
::HP_Set_FN_Server_OnShutdown(m_pListener, OnShutdown);
}
TGpsServer::~TGpsServer()
{
// 销毁 Socket 对象
::Destroy_HP_TcpPullServer(m_pServer);
// 销毁监听器对象
::Destroy_HP_TcpPullServerListener(m_pListener);
}
En_HP_HandleResult __stdcall TGpsServer::OnPrepareListen(HP_Server pSender, unsigned int soListen)
{
setlocale(LC_ALL, "chs");
TCHAR szAddress[50];
int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
USHORT usPort;
::HP_Server_GetListenAddress(pSender, szAddress, &iAddressLen, &usPort);
return HR_OK;
}
En_HP_HandleResult __stdcall TGpsServer::OnAccept(HP_Server pSender, HP_CONNID dwConnID, unsigned int soClient)
{
BOOL bPass = TRUE;
TCHAR szAddress[50];
int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
USHORT usPort;
::HP_Server_GetRemoteAddress(pSender, dwConnID, szAddress, &iAddressLen, &usPort);
char buff[100] = {0};
sprintf(buff,"接入客户端[ID=%d]:IP=%s,端口=%d",dwConnID, szAddress, usPort);
strcpy(g_szBuff,buff);
SendMessage(m_hWnd,WM_MAINFORM_SHOW,0,0);
SendMessage(m_hWnd,WM_MAINFORM_SHOW,0,4);
STExtraData * pStExtraData = new STExtraData;
pStExtraData->ConnID = dwConnID;
strcpy(pStExtraData->szIP,szAddress);
pStExtraData->nPort = usPort;
if(bPass = HP_Server_SetConnectionExtra(pSender,dwConnID, pStExtraData))
return bPass ? HR_OK : HR_ERROR;
}
En_HP_HandleResult __stdcall TGpsServer::OnSend(HP_Server pSender, HP_CONNID dwConnID, const BYTE* pData, int iLength)
{
return HR_OK;
}
En_HP_HandleResult __stdcall TGpsServer::OnReceive(HP_Server pSender, HP_CONNID dwConnID, int iLength)
{
STExtraData * pStExtraData = FindExtraData(pSender,dwConnID);
AnsiString strTemp = AnsiString().sprintf("接收客户端数据包[ID=%d],数据长度=%d,IP=%s,Port=%d",
dwConnID,iLength,pStExtraData->szIP,pStExtraData->nPort);
strcpy(g_szBuff,strTemp.c_str());
SendMessage(m_hWnd,WM_MAINFORM_SHOW,0,0);
HP_TcpPullServer_Fetch(pSender,dwConnID,g_szBuff,iLength);
SendMessage(m_hWnd,WM_MAINFORM_SHOW,iLength,3);
return HR_OK;
}
En_HP_HandleResult __stdcall TGpsServer::OnClose(HP_Server pSender, HP_CONNID dwConnID, En_HP_SocketOperation enOperation, int iErrorCode)
{
AnsiString strTemp;
if(iErrorCode == SE_OK)
strTemp = AnsiString().sprintf("客户端[ID=%d]正常退出",dwConnID);
else
strTemp = AnsiString().sprintf("客户端[ID=%d]发生错误:操作码%d,错误码%d",dwConnID,enOperation,iErrorCode);
strcpy(g_szBuff,strTemp.c_str());
SendMessage(m_hWnd,WM_MAINFORM_SHOW,0,0);
SendMessage(m_hWnd,WM_MAINFORM_SHOW,0,4);
RemoveExtraData(pSender,dwConnID);
return HR_OK;
}
En_HP_HandleResult __stdcall TGpsServer::OnShutdown(HP_Server pSender)
{
AnsiString strTemp = "服务器关闭";
strcpy(g_szBuff,strTemp.c_str());
PostMessage(m_hWnd,WM_MAINFORM_SHOW,0,0);
PostMessage(m_hWnd,WM_MAINFORM_SHOW,0,2);
return HR_OK;
}
VOID TGpsServer::StartServer(HWND hWnd)
{//启动服务器
m_hWnd = hWnd;
if (!HP_Server_Start(m_pServer, "0.0.0.0", PORT))
{
m_ServerStart = FALSE;
OLETRACE("服务器启动出错:%d,%s", ::HP_Server_GetLastError(m_pServer),
::HP_Server_GetLastErrorDesc(m_pServer));
AnsiString strTemp;
strTemp.sprintf("服务器启动出错:%d,%s", ::HP_Server_GetLastError(m_pServer),
::HP_Server_GetLastErrorDesc(m_pServer));
strcpy(g_szBuff,"服务器启动,绑定0.0.0.0:7890!");
PostMessage(m_hWnd,WM_MAINFORM_SHOW,0,0);
}
else
{
m_ServerStart = TRUE;
strcpy(g_szBuff,"服务器启动,绑定0.0.0.0:7890!");
PostMessage(m_hWnd,WM_MAINFORM_SHOW,0,0);
PostMessage(m_hWnd,WM_MAINFORM_SHOW,0,1);
}
}
VOID TGpsServer::StopServer()
{//停止服务器
::HP_Server_Stop(m_pServer);
m_ServerStart = FALSE;
}
STExtraData* TGpsServer::FindExtraData(HP_Server pSender,HP_CONNID dwConnID)
{
PVOID pInfo = NULL;
bool ret = HP_Server_GetConnectionExtra(pSender,dwConnID, &pInfo);
return (STExtraData*)pInfo;
}
void TGpsServer::RemoveExtraData(HP_Server pSender,HP_CONNID dwConnID)
{
STExtraData* pInfo = FindExtraData(pSender, dwConnID);
assert(pInfo != NULL);
delete pInfo;
}
上述代码参考了作者的 C#、VC2015 的代码,改写后,可以正常运行,效果很好。