0

小伙伴们怎么了,希望你们没事!好吧,问题是我正在做一个聊天客户端/服务器应用程序,但是对服务器进行了一些测试,我发现我在发送消息时遇到了问题。我正在使用结构、套接字和 DWORD WINAPI 线程......所以结构中的代码是:

DWORD WINAPI threadSendMessages(LPVOID vpParam); //THREAD
typedef struct messagesServerChat{ //STRUCT

 const char *messageServEnv;

}MESSAGE, *SMESSAGES;

然后在 main 方法中,我调用结构来使用 const char messageServEnv,一个 HeapAlloc 为要发送消息的线程提供一些内存,以及一个用于存储消息的 char 变量

char mServer[1024] = ""; //variable to pre-store the message
SMESSAGES messages; //call the struct
messages  = (SMESSAGES) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MESSAGE));

在 main 方法中,我要求用户插入他想要发送的消息,然后我使用结构来存储消息并将其作为参数发送到线程:

cout<<"Dear user, please insert your message: ";

setbuf(stdin, NULL);
fgets(mServer, 1024, stdin);
messages->messageServEnv = mServer;
DWORD hSend; //send the parameters to the thread function
HANDLE sendThread = CreateThread(0, 0, threadSendMessages, mServer, 0, &hSend);

最后是线程代码函数

DWORD WINAPI threadSendMessages(LPVOID lpParam){

SMESSAGES messages;
messages = (SMESSAGES)lpParam; 
int mesa;
mesa = send(sConnect, (char *)messages->messageServEnv, sizeof messages->messageServEnv, 0);
//sConnect is the socket
//messages = to use the struct, and messageServEnv is the struct data that should contain the message   
return 0;
}

--Edit-- 我使用 Remy 的解决方案解决了很多问题,但也许我遗漏了一些东西……在 Thread threadSendMessages(SMESSAGES lpMessage)

char *ptr = messages->messageServEnv;
int len = strlen(messages->messageServEnv);

我得到一个错误,说消息是未定义的,然后,我改为:

SMESSAGES messages;
char *ptr = messages->messageServEnv;
int len = strlen(messages->messageServEnv);

现在我可以使用消息和结构值messageServEnv但是如果我开始调试 Visual Studio 并尝试发送消息,我会收到一个错误,提示消息在未初始化的情况下被使用,然后我将该部分更改为

SMESSAGES messages = new MESSAGE;

现在我可以向客户端发送消息,但只能发送字符和垃圾代码

4

1 回答 1

0

您需要为每个消息的字符串数据动态分配内存,然后在完成发送后让线程释放内存。

您还将错误的指针传递给 of 的lpParameter参数CreateThread(),您传递的是char[]缓冲区而不是分配的MESSAGE结构。

sizeof()您在调用时也在使用send(). 由于您messageServEnv是一个char*指针,sizeof()因此将返回 4(32 位)或 8(64 位)而不是所指向的字符串的实际大小。

我建议将char[]缓冲区直接移动到结构中,而不是使用指向外部缓冲区的指针,例如:

typedef struct messagesServerChat
{
    char messageServEnv[1024]; 
}
MESSAGE, *SMESSAGES; 

DWORD WINAPI threadSendMessages(SMESSAGES lpMessage);

.

cout << "Dear user, please insert your message: "; 
setbuf(stdin, NULL); 

SMESSAGES message = new MESSAGE;
fgets(message->messageServEnv, sizeof(message->messageServEnv), stdin); 

DWORD hSend;
HANDLE sendThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&threadSendMessages, message, 0, &hSend); 
if (!sendThread)
    delete message;

.

DWORD WINAPI threadSendMessages(SMESSAGES lpMessage)
{ 
    // send() is not guaranteed to send the entire message
    // in one go, so call it in a loop...

    char *ptr = lpMessage->messageServEnv;
    int len = strlen(lpMessage->messageServEnv); // or sizeof() if you really want to send all 1024 bytes instead

    while (len > 0)
    {
        int mesa = send(sConnect, ptr, len, 0); 
        if (mesa > 0)
        {
            ptr += mesa;
            len -= mesa;
            continue;
        }

        // this is only needed if you are using a non-blocking socket...
        if ((mesa == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
        {
            fd_set fd;
            FD_ZERO(&fd);
            FD_SET(sConnect, &fd);

            timeval tv;
            tv.tv_sec = 5;
            tv.tv_usec = 0;

            if (select(0, NULL, &fd, NULL, &tv) > 0)
                continue;
        }

        ... error handling ...
        break;
    }

    delete message;
    return 0; 
} 

如果你想传递一个动态长度的字符串,你最好使用 astd::string而不是 a char[]

typedef struct messagesServerChat
{
    std::string messageServEnv; 
}
MESSAGE, *SMESSAGES; 

DWORD WINAPI threadSendMessages(SMESSAGES lpMessage);

.

cout << "Dear user, please insert your message: "; 
setbuf(stdin, NULL); 

SMESSAGES message = new MESSAGE;
getline(stdin, message->messageServEnv); 

DWORD hSend;
HANDLE sendThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&threadSendMessages, message, 0, &hSend); 
if (!sendThread)
    delete message;

.

DWORD WINAPI threadSendMessages(SMESSAGES lpMessage)
{ 
    // send() is not guaranteed to send the entire message
    // in one go, so call it in a loop...

    char *ptr = lpMessage->messageServEnv.c_str();
    int len = lpMessage->messageServEnv.length(); // or sizeof() if you really want to send all 1024 bytes instead

    while (len > 0)
    {
        int mesa = send(sConnect, ptr, len, 0); 
        if (mesa > 0)
        {
            ptr += mesa;
            len -= mesa;
            continue;
        }

        // this is only needed if you are using a non-blocking socket...
        if ((mesa == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
        {
            fd_set fd;
            FD_ZERO(&fd);
            FD_SET(sConnect, &fd);

            timeval tv;
            tv.tv_sec = 5;
            tv.tv_usec = 0;

            if (select(0, NULL, &fd, NULL, &tv) > 0)
                continue;
        }

        ... error handling ...
        break;
    }

    delete message;
    return 0; 
} 
于 2012-04-18T20:54:13.750 回答