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

--編集--Remyのソリューションを使用して多くの問題を修正しましたが、スレッドに何かが足りない可能性があります... 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

各メッセージの文字列データに動的にメモリを割り当て、送信が終了したらスレッドにメモリを解放させる必要があります。

lpParameterまた、のパラメータに間違ったポインタを渡しています。割り当てられた構造体の代わりにバッファCreateThread()を渡しています。char[]MESSAGE

sizeof()を呼び出すときにも使用していsend()ます。yourmessageServEnvchar*ポインタなので、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; 
} 
于 2012-04-18T20:54:13.750 に答える