WSASend 缓冲区到字符串

WSASend Buffer to String

如何将 Winsock2 WSASend() 缓冲区转换为字符串?

这是我目前的代码,只写了很多I个字符。

int WINAPI Hook_WSASend(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, DWORD a4, LPWSAOVERLAPPED a5, LPWSAOVERLAPPED_COMPLETION_ROUTINE a6)
{
    int rv = 0;
    char * buf = "";
    WSABUF * wb = a1;

    for(int i = 0; i == a2; i++){
        strcpy_s(buf, wb[i].len, wb[i].buf);
    }

    fopen_s(&pWSASendLogFile, "C:\WSASendLog.txt", "a+");
    fprintf(pWSASendLogFile, "%s\n", buf);
    fclose(pWSASendLogFile);
    rv = Real_WSASend(a0,a1,a2,a3,a4,a5,a6);
    return rv;
}

正如 Remy Lebeau 所问,我正在添加更多关于我需要实现的信息。

我需要在字符串中包含缓冲区,因为:

为了更好地解释我在做什么,这是我目前拥有的 Winsock send() 代码。我必须对 WSASend().

做同样的事情
int WINAPI Hook_Send(SOCKET s, const char* buf, int len, int flags)
{
    /*
    fopen_s(&pSendLogFile, "C:\SendLog.txt", "a+");
    fprintf(pSendLogFile, "%s\n", buf);
    fclose(pSendLogFile);
    */
    curSocket = s;
    if(Filtering){
        PipeHeader ph;
        string p(buf);
        if(p.find("<TalkMsg") == 0){
            ph.command = 5;
            ph.sockid = s;
            ph.datasize = len;
            if(SendPipeHeader((char*)&ph, sizeof(ph))){
                if(SendPipeData(buf, len)){
                    return len;
                }
            }
        }
    }

    return Real_Send(s, buf, len, flags);
}

正如@enhzflep 在评论中所说,您没有正确管理 buf 变量。你甚至根本不需要它。只需将源缓冲区按原样直接写入文件即可:

int WINAPI Hook_WSASend(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, DWORD a4, LPWSAOVERLAPPED a5, LPWSAOVERLAPPED_COMPLETION_ROUTINE a6)
{
    fopen_s(&pWSASendLogFile, "C:\WSASendLog.txt", "a+");
    for(DWORD i = 0; i < a2; i++)
        fwrite(a1[i].buf, 1, a1[i].len, pWSASendLogFile);
    fprintf(pWSASendLogFile, "\n");
    fclose(pWSASendLogFile);

    int rv = Real_WSASend(a0,a1,a2,a3,a4,a5,a6);
    return rv;
}

Update:您的 send() 挂钩假设 buf 始终以 null 结尾,但事实并非如此。将 buf 数据复制到 `string:

时,您必须使用提供的 len
int WINAPI Hook_Send(SOCKET s, const char* buf, int len, int flags)
{
    /*
    fopen_s(&pSendLogFile, "C:\SendLog.txt", "a+");
    fwrite(buf, 1, len, pSendLogFile);
    fprintf(pSendLogFile, "\n");
    fclose(pSendLogFile);
    */
    curSocket = s;
    if(Filtering){
        PipeHeader ph;
        string p(buf, len); // <-- here
        if(p.find("<TalkMsg") == 0){
            ph.command = 5;
            ph.sockid = s;
            ph.datasize = len;
            if(SendPipeHeader((char*)&ph, sizeof(ph))){
                if(SendPipeData(buf, len)){
                    return len;
                }
            }
        }
    }

    return Real_Send(s, buf, len, flags);
}

您必须在 WSASend() 挂钩中做类似的事情,将所有 WSABUF 缓冲区的总长度考虑在内:

int WINAPI Hook_WSASend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED                    lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
    /*
    fopen_s(&pWSASendLogFile, "C:\WSASendLog.txt", "a+");
    for(DWORD i = 0; i < dwBufferCount; i++)
        fwrite(lpBuffers[i].buf, 1, lpBuffers[i].len, pWSASendLogFile);
    fprintf(pWSASendLogFile, "\n");
    fclose(pWSASendLogFile);
    */
    curSocket = s;
    if(Filtering){
        PipeHeader ph;
        string p;
        size_t len = 0;
        for(DWORD i = 0; i < dwBufferCount; i++) {
            len += lpBuffers[i].len;
        }
        p.reserve(len);
        for(DWORD i = 0; i < dwBufferCount; i++) {
            p.append(lpBuffers[i].buf, lpBuffers[i].len);
        }
        if(p.find("<TalkMsg") == 0){
            ph.command = 5;
            ph.sockid = s;
            ph.datasize = len;
            if(SendPipeHeader((char*)&ph, sizeof(ph))){
                if(SendPipeData(p.c_str(), len)){
                    if (lpNumberOfBytesSent){
                        *lpNumberOfBytesSent = len;
                    }
                    if (lpCompletionRoutine) {
                        lpCompletionRoutine(0, len, lpOverlapped, 0);
                    }
                    return 0;
                }
            }
        }
    }

    return Real_WSASend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine);
}

也就是说,由于 TCP 的流式特性,这种过滤代码不是很可靠。当存在 "<TalkMsg" 时,无法保证输入数据在单次发送中代表完整的消息,甚至无法保证 "<TalkMsg" 本身在单次发送中完成。您真正需要做的是将出站数据按原样保存到每个套接字缓冲区,然后解析缓冲区以查找完整消息,仅将完整消息传递到您的管道并将它们从缓冲区中删除,将部分数据留在由后续发送完成的缓冲区。