Question

What's up guys, hope you are ok ! well, the problem is that I'm doing a chat client/server aplication but doing some tests with the server, I found out that I have a problem sending messages. I'm using a struct, sockets and DWORD WINAPI threads... So the code in the struct is:

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

 const char *messageServEnv;

}MESSAGE, *SMESSAGES;

then in the main method I call the struct to use the const char messageServEnv, a HeapAlloc to give some memory to the thread that is going to send the message and a char variable that I use to store the message

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

in the main method, I ask the user to insert the message that he wants to send and I use the struct to store the message and send it to the thread as a parameter:

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

and finally the thread code function

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-- I fix a lot of problems using Remy's solution but maybe I'm missing something... in the Thread threadSendMessages(SMESSAGES lpMessage)

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

I get and error that says messages is undifined, then, I changed to:

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

now I can use messages and struct value messageServEnv but if I start debugging visual studio and I try to send a message, I get an error that says messages is used without being initialized, then I change that part to

SMESSAGES messages = new MESSAGE;

and now I can send messages to client but only characters and garbage code

Was it helpful?

Solution

You need to dynamically allocate the memory for each message's string data and then have the thread free the memory when finished sending it.

You are also passing the wrong pointer to the lpParameter parameter of CreateThread(), you are passing your char[] buffer instead of your allocated MESSAGE struct.

You are also using sizeof() when calling send(). Since your messageServEnv is a char* pointer, sizeof() will return 4 (32-bit) or 8 (64-bit) instead of the actual size of the string that is being pointed at.

I would suggest moving the char[] buffer directly into the struct instead of using a pointer to an external buffer, eg:

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

If you want to pass a dynamically-lengthed string instead, you are better off using a std::string instead of 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; 
} 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top