基于C+;代码在PHP中创建字节数据并将其传递给套接字+;

基于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

如果这个标题没有让你困惑的话,我会看看我能在这里做些什么。我有一个C++ DLL的来源,它将TCP流量传递给服务器。我相信所有相关的C++代码都在下面:

#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');