gpt4 book ai didi

c++ - 不能以 NULL 终止接收缓冲区

转载 作者:可可西里 更新时间:2023-11-01 02:51:00 27 4
gpt4 key购买 nike

尝试从这里解决问题:https://stackoverflow.com/questions/40136218/c-non-sense-data-between-recv-calls/

我已经尝试了很多方法来从 recv 中对 buf 进行空终止,在展示我尝试过的内容之前,这是我 Hook recv 函数并记录数据:

typedef int (WINAPI *SendPtr)(SOCKET s, const char* buf, int len, int flags);
HMODULE hLib = LoadLibrary("wsock32.dll");
SendPtr pSend = (SendPtr)GetProcAddress(hLib, "send");
int WINAPI MySend(SOCKET s, const char* buf, int len, int flags);
SendPtr pRecv = (SendPtr)GetProcAddress(hLib, "recv");
int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags);
extern HMODULE hDLL;
__declspec(dllexport) LRESULT WINAPI MyProcedure(int code, WPARAM wp, LPARAM lp);
HMODULE g_hModule = NULL ;

INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:

CreateConsole();
g_hModule = hDLL;
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pSend, MySend);
if(DetourTransactionCommit() == NO_ERROR)


DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pRecv, MyRecv);
if(DetourTransactionCommit() == NO_ERROR)


return TRUE;

case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}


// ---------- SEND ------------


int WINAPI MySend(SOCKET s, const char* buf, int len, int flags)
{
int i = 0;
int ret = pSend(s, buf, len, flags);
while (i < ret && buf)
{
int len = strlen(buf) +1;
buf += len;
i += len;
}


return ret;
}

// ---------- RECV ------------

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags)
{

int i = 0;
int ret = pRecv(s, buf, len, flags);

while (i < ret && buf)
{
cout<<buf<<endl;

int len = strlen(buf) +1;
buf += len;
i += len;
}

return ret;
}

我测试了什么

我试过检查 buf 的字节数,然后添加终止符:

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags)
{

int i = 0;
int ret = pRecv(s, buf, len, flags);
buf[ret] = '\0';

while (i < ret && buf)
{
cout<<buf<<endl;

int len = strlen(buf) +1;
buf += len;
i += len;
}

return ret;
}

结果呢?数据被损坏为垃圾数据,如 @ÿÿÿ^¡5~ç 和我尝试提取数据的程序,崩溃。

我试过将数据存储到 vector 中。

std::vector<char> buffer(1025);

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags)
{

int i = 0;
int ret = pRecv(s, buffer.data(), buffer.size() - 1, 0);



while (i < ret && buffer.data())
{

cout<<buffer.data()<<endl;

int len = strlen(buffer.data()) +1;
buf += len;
i += len;

}


return ret;
}

有点工作,存储一些数据然后程序崩溃,更改 vector 的大小也不起作用。

最佳答案

使用 TCP...

您不能将来自网络的任意数据视为字符串。您需要建立一个协议(protocol)来确定数据的格式以及何时收到您可以理解的数据量。

然后您需要从网络接收数据,直到您获得了可以理解的数据量,然后再尝试解释它。

通过 TCP 发送字符串的简单协议(protocol)是

[X = 32 bit network byte order unsigned int string length]
Next X bytes are the string

然后,在你得到 X + 4 个字节后,你可以解释数据,从 4 个字节的偏移量开始作为字符串,并且知道你在发送它时包含了一个 nul 终止符,或者放入一个 nul 终止符在缓冲区末尾的客户端。超出 X + 4 字节的任何数据都将成为下一个字符串的开始,否则客户端在发送完数据后将断开连接。

此时您可以打印它。

如果你想要非常原始的调试数据,你可以简单地打印出你收到的每个字节的十六进制值,如下所示:

Recv returned 4 bytes:  0xa7 0x42 0x8b 0x44

每次都会收到返回,但这并不经常有用。

关于c++ - 不能以 NULL 终止接收缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40153717/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com