基于C+;代码在PHP中创建字节数据并将其传递给套接字+;
如果这个标题没有让你困惑的话,我会看看我能在这里做些什么。我有一个C++ DLL的来源,它将TCP流量传递给服务器。我相信所有相关的C++代码都在下面:基于C+;代码在PHP中创建字节数据并将其传递给套接字+;,php,c++,sockets,unicode,pack,Php,C++,Sockets,Unicode,Pack,如果这个标题没有让你困惑的话,我会看看我能在这里做些什么。我有一个C++ DLL的来源,它将TCP流量传递给服务器。我相信所有相关的C++代码都在下面: #define HRD_MSG_SANITY1 0x1234ABCD #define HRD_MSG_SANITY2 0xABCD1234 typedef struct{ unsigned int nSize; unsigned int nSanity1; unsigned int nSan
#define HRD_MSG_SANITY1 0x1234ABCD
#define HRD_MSG_SANITY2 0xABCD1234
typedef struct{
unsigned int nSize;
unsigned int nSanity1;
unsigned int nSanity2;
unsigned int nChecksum;
WCHAR szText[1];
} HRD_MSG_BLOCK;
CString strMessage = "this is a test\n";
// I added this - the rest of the code
// to determine this is unnecessary for
// the context of this question.
//
// Allocate.
//
int nMsgBytes = sizeof(HRD_MSG_BLOCK) + sizeof(TCHAR) * (strMessage.GetLength() + 1);
HRD_MSG_BLOCK* pMsgBlock = (HRD_MSG_BLOCK*) new BYTE[nMsgBytes];
BYTE* pMsgBuffer = (BYTE*)pMsgBlock;
ZeroMemory(pMsgBlock, nMsgBytes);
pMsgBlock->nSize = nMsgBytes;
pMsgBlock->nSanity1 = HRD_MSG_SANITY1;
pMsgBlock->nSanity2 = HRD_MSG_SANITY2;
pMsgBlock->nChecksum = 0;
_tcscpy(pMsgBlock->szText, strMessage);
for (int nSendLoop = 0; (nSendLoop < MAX_SENDS) && (nToSend > 0); nSendLoop++) {
//
// Send data to this port, max of 32k (0x8000).
//
int nSendSize = min(nToSend, 0x8000);
int nSentCount = (int)::send(g_socket, (char*)&pMsgBuffer[nSent], nSendSize, 0);
//
// Error.
//
if (nSentCount == SOCKET_ERROR) {
CSocketError error(::WSAGetLastError());
//
// Report the error.
//
g_strLastError.Format(_T("Error sending %u bytes to socket %u - %s"),
nSendSize,
g_socket,
error.Text());
} else {
nSent += nSentCount;
nToSend -= nSentCount;
}
}
然后我创建套接字,并使用socket\u write
发送$binarydata
显然,我不能使用pack()
,因为我不能将类对象($pMsgBlock)转换为int(作为pack()的第二个参数是必需的)。我使用utf8_encode()是因为DLL文档中说:
szText是作为UNICODE(宽)字符串发送的文本
我很难确定C++的DLL发送到套接字的内容,所以我基本上猜测我需要在PHP中发送什么。< /P>
我可以使用帮助确定C++代码的确切发送方式,以及如何在PHP中执行同样的操作。 谢谢。
您不能打包()整个对象,但可以打包()并连接成员。比如$packed = pack('I', $pMsgBlock->nSize)
.pack('I', $pMsgBlock->nSanity1)
.pack('I', $pMsgBlock->nSanity2)
.pack('I', $pMsgBlock->nChecksum)
.mb_convert_encoding($pMsgBlock->szText, 'UTF-16');
我应该补充一点,我没有权限修改接收端,甚至无法读取代码。我所能做的就是查看上面的C++源代码(发送结束),并尝试发送相同的东西。Windows中的一个宽字符串是UTF 16,而不是UTF 8。谢谢,所以我可以将UTF8YEnEngEnter($string)改为MbOnExchange编码($string,UTF 16)。但是,我仍然无法打包对象,就像在C++中那样完成套接字的发送,太棒了!我想这就是我想要的。。这是我见过的最接近的一次,但我还不确定szText的编码是否正确。。服务器仍无法识别该命令。我肯定离这儿很近。。我在文档中注意到“所有请求和回复都以十六进制0x00终止”。因此,也许我只需要在末尾添加一个\0,或另一个包('I',0);当然,如果需要,请附加“\0”。虽然大小和终止都很奇怪,但是,我终于收到了服务器的响应,这意味着有些东西正在工作。不幸的是,反应不是预期的,所以我还有一些工作要做。看起来它使用的响应格式与我们发送的相同:将结构作为二进制数据传递。我将对其进行更多的修改,并尝试确定上述方法是否是发送数据的正确方法。我在控制台上得到的回复是“44”。我必须等到回家,看看这是否接近我想要看到的,但我怀疑不是。任务成功!我使用netmon.exe评估来自已知良好客户端的传入数据包,并比较了来自我正在处理的php脚本的传入数据包。UTF-16实际上需要是“UTF-16LE”,我必须对上面的答案做一些修改才能使其工作,但我们终于成功了!谢谢蒂诺!
$packed = pack('I', $pMsgBlock->nSize)
.pack('I', $pMsgBlock->nSanity1)
.pack('I', $pMsgBlock->nSanity2)
.pack('I', $pMsgBlock->nChecksum)
.mb_convert_encoding($pMsgBlock->szText, 'UTF-16');