Socket recv() 将我的字符串变成了 char "C:\User" 'C'

Socket recv() made my string into a char "C:\User" 'C'

为什么字符串 a return 'C' 而不是 "C:\Users\Desktop\Project phoneedge\ForMark\Top"?

当我在一个空的 c++ 项目中测试它时,在我将我的一些代码从 ThreadFunction 移动到 StartButton 之前它工作了(UI 应该不断更新但是套接字 recv() 正在阻塞它导致它只更新一次所以我将 UI 代码移动到 startbutton)

这是服务器代码,按下开始按钮后,启动套接字并创建一个线程来 运行 listen() accept() 和 recv()。关闭按钮关闭套接字和线程。

服务器代码(MFC项目)

void CUIServerDlg::StartButton()
{
    WSADATA Winsockdata;
    int iTCPClientAdd = sizeof(TCPClientAdd);
    WSAStartup(MAKEWORD(2, 2), &Winsockdata);

    TCPServerAdd.sin_family = AF_INET;
    TCPServerAdd.sin_addr.s_addr = inet_addr("127.0.0.1");
    TCPServerAdd.sin_port = htons(8000);

    TCPServersocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    bind(TCPServersocket, (SOCKADDR*)&TCPServerAdd, sizeof(TCPServerAdd));

    bRunning = true;
    hthread = CreateThread(NULL, 0, ThreadFunction, this, 0, &ThreadID);
    WaitForSingleObject(hthread, INFINITE);

    funRunning = true;
    while (funRunning == true) {
        vector<string> caseOne;
    

        /*string a;
        char RecvBuffer[512];//this is the declaration in member class
        int iRecvBuffer = strlen(RecvBuffer) + 1;*/

        **a = RecvBuffer;**//a is a String, RecvBuffer is a path name like c:\user..
        //Find files,This part of code is left out because it should not effect the question
        //put the files found in a vector, then display it on a listbox
        for (string fileVec : caseOne) {

            CString fileunderPath;
            string filevector1 = fileVec;
            fileunderPath = filevector1.c_str();//conversion for AddString
            list1.AddString(fileunderPath);
        }
        
        Sleep(1000);//The code updates every 1 second , when file names are modified is displays immediately.
    }    
}

我想将 Sleep(1000) 更改为 WaitForSingleObject() 以替换 WM_Timer 用于分配,但我不知道如何,因为您需要一个句柄,我是否创建另一个线程?

void CUIServerDlg::CloseButton()
{
    bRunning = false;
    funRunning = false;

    WaitForSingleObject(hthread, INFINITE);
    CloseHandle(hthread);
    closesocket(TCPServersocket);
}

所以在这个项目之前我从来没有学过任何关于套接字和线程的知识,下面代码的想法是使用一个线程来运行一个while循环来不断地检查新的客户端来发送东西,如果思路有误,请务必指正。

DWORD WINAPI CUIServerDlg::ThreadFunction(LPVOID lpParam) {

    CUIServerDlg* This = (CUIServerDlg*)lpParam;
    while (This->bRunning == true) {

        int iListen = listen(This->TCPServersocket, 10);
        if (iListen == INVALID_SOCKET)
            OutputDebugString(_T("FAIL LISTEN\n"));

        This->sAccecpSocket = accept(This->TCPServersocket, (SOCKADDR*)&This->iTCPClientAdd, &This->iTCPClientAdd);
        recv(This->sAccecpSocket, This->RecvBuffer, This->iRecvBuffer, 0);
    }

    return 0;
}

客户端代码(空 c++ 项目)

int main(){
    string a = "C:\Users\Desktop\Project phoneedge\ForMark\Top";
    const char* SenderBuffer = a.c_str();
    int iSenderBuffer = strlen(SenderBuffer) + 1;

    WSAStartup(MAKEWORD(2, 2), &WinSockData);
    TCPClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    TCPServerAdd.sin_family = AF_INET;
    TCPServerAdd.sin_addr.s_addr = inet_addr("127.0.0.1");
    TCPServerAdd.sin_port = htons(8000);

    connect(TCPClientSocket,(SOCKADDR*)&TCPServerAdd,sizeof(TCPServerAdd));

    send(TCPClientSocket, SenderBuffer, iSenderBuffer, 0);
    closesocket(TCPClientSocket);

    WSACleanup();
    system("PAUSE");
    return 0;
}

TCP协议以字节流方式传递数据。

意思是客户端一个字节一个字节的传递数据,而不是一次传递所有的数据。

当您收到来自客户端的数据时。过关手续可能还没有完成

因此需要调用一次recv调用接收到部分数据后检查数据是否传递完毕,然后保存子数据,直到接收到所有数据。