【问题标题】:Struct and Thread DWORD WINAPI结构和线程 DWORD WINAPI
【发布时间】:2012-04-18 15:31:54
【问题描述】:

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

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

 const char *messageServEnv;

}MESSAGE, *SMESSAGES;

然后在 main 方法中,我调用 struct 以使用 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 方法中,我要求用户插入他想要发送的消息,然后我使用 struct 来存储消息并将其作为参数发送到线程:

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;
}

--编辑--我使用 Remy 的解决方案解决了很多问题,但也许我遗漏了一些东西......在线程 threadSendMessages(SMESSAGES lpMessage)

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

我收到消息未定义的错误,然后,我改为:

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

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

SMESSAGES messages = new MESSAGE;

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

【问题讨论】:

  • 关于编辑,请参阅我更新的答案。

标签: sockets visual-c++ struct dword


【解决方案1】:

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

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

您在调用send() 时也使用sizeof()。由于您的 messageServEnvchar* 指针,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; 
} 

如果您想传递一个动态长度的字符串,最好使用std::string 而不是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; 
} 

【讨论】:

  • 什么样的错误?你需要更具体。请不要在评论中添加太多代码,而是编辑您的原始问题。
  • 对不起,我使用评论发送了新问题,我用新错误编辑了原始问题,我知道我在代码中遗漏了一些东西,因为我可以发送消息但只能发送垃圾代码和一些符号
猜你喜欢
  • 2011-12-31
  • 2011-01-31
  • 2020-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多