尝试从此处解决问题:https://stackoverflow.com/questions/40136218/c-non-sense-data-between-recv-calls/
在尝试展示我尝试的内容之前,我已经尝试了很多方法从buf
取消终止recv
,这里是我挂钩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~ç
和我试图提取数据的程序,崩溃。
我已尝试将数据存储到矢量中。
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;
}
有点工作,存储一些数据然后程序崩溃,改变矢量的大小也不起作用。
答案 0 :(得分:1)
使用TCP ...
您不能将来自网络的任意数据视为字符串。您需要建立一个协议来确定数据的格式化方式,以及何时收到一些您可以理解的数据。
然后,您需要从网络接收数据,直到您在尝试解释之前获得了大量可以理解的数据。
用于通过TCP发送字符串的简单协议将是
[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
每次收到回报,但这通常没那么有用。