-1

回答:(7時間経っても質問に答えられないため:/)わかりました、次の変更で解決しました:

struct RecvDataModel
{
    int sockAddr;
    string inData; //old: char *inData;
};

void Client::Recv(int sockAddr, char *inData)
{
    cout << inData << endl;
    RecvDataModel *outData = new RecvDataModel();
    outData->sockAddr = sockAddr;
    outData->inData = string(inData);//old outData->inData = inData;
    pthread_t rThr;
    pthread_create(&rThr, NULL, ProcessData, outData);
}

文字列は自動的に char* 形式を修正すると思います。そうしないと何も理解できません!

そして今、私は聞きたいです: string と char のパフォーマンスは同じですか? char* の代わりに文字列を使用することに問題はありますか (pointers-void*- を除く)?

質問: -inData と sockAddr はソケットから送信されました。これはマルチクライアント チャット サーバーです。ここでは、sockAddr を ProcessData に送信できますが、inData は送信できません。壊れた形式で変更されます(「testDataTextÿñ€ÿñ:¥øv:Y」のように、「testDataText」を送信して変更しました)。別の char* を作成して for ループですべてコピーしようとしましたが、この時点で "te%s;t" のようなデータを送信すると、再び壊れた形式で変更されます。私に何ができる?

struct RecvDataModel
{
    int sockAddr;
    char *inData;
};

void *ProcessData(void *arg);

void Client::Recv(int sockAddr, char *inData)
{
    RecvDataModel * outData = new RecvDataModel();
    outData->sockAddr = sockAddr;
    outData->inData = inData;
    pthread_t rThr;
    pthread_create(&rThr, NULL, ProcessData, outData);
}

void *ProcessData(void *arg)
{
    RecvDataModel *inData = (RecvDataModel*)arg;
    cout << inData->inData << endl;
    return 0;
}

inData と sockAddr はここから来ました (クライアント クラス):

#include <winsock2.h>

class Client
{
private:
    int mySock;
    int sockAddr;
    bool logged;
    void *listen(void)
    {
        int numBytes;
        char buffer[5120];
        while(1)
        {
            numBytes = recv(mySock, buffer, 5120, 0);
            if(numBytes == 0 || numBytes == -1)
            {
                Drop(mySock);
                mySock = 0;
                sockAddr = 0;
                return 0;
            }
            Recv(sockAddr, buffer);
            memset(buffer, 0, sizeof buffer);
        }
        return 0;
    }
public:
    void SetSock(int sock)
    {
        mySock = sock;
    }
    void SetSockAddr(int addr)
    {
        sockAddr = addr;
    }
    void Logged(bool status)
    {
        logged = status;
    }
    int GetSock()
    {
        return mySock;
    }
    int GetSockAddr()
    {
        return sockAddr;
    }
    bool IsLogged()
    {
        return logged;
    }
    static void *Listen(void *arg)
    {
        return ((Client*)arg)->listen();
    }
    static void Recv(int sockAddr, char *inData);
    static void Drop(int sockAddr);
};

およびすべての main.cpp

#define PORT 9696
#define MAXCONN 9999
#define BACKLOG 128

#include <winsock2.h>
#include <pthread.h>
#include <iostream>
#include "Client.cpp"

using namespace std;

struct RecvDataModel
{
    int sockAddr;
    char *inData;
};

Client m_Clients[MAXCONN];

void *AcceptClients(void *arg);
void *HandleClient(void *arg);
void *DropClient(void *arg);
void *ProcessData(void *arg);

void Client::Recv(int sockAddr, char *inData)
{
    cout << inData << endl;
    RecvDataModel *outData = new RecvDataModel();
    outData->sockAddr = sockAddr;
    outData->inData = inData;
    pthread_t rThr;
    pthread_create(&rThr, NULL, ProcessData, outData);
}

void Client::Drop(int sockAddr)
{
    pthread_t dThr;
    pthread_create(&dThr, NULL, DropClient, (void*)sockAddr);
}

int main()
{
    /* WinSock initialization::START */
    WSADATA wsaData;
    if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
    {
        cout << "WSA initialization failed!";
        WSACleanup();
        return 1;
    }
    /* WinSock initialization::END */
    SOCKET m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    //--> TCP Socket: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
    //--> UDP Socket: socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
    if(m_Socket == INVALID_SOCKET)
    {
        cout << "Cannot create server socket!";
        WSACleanup();
        return 1;
    }
    sockaddr_in m_Inf;
    m_Inf.sin_family = AF_INET;
    m_Inf.sin_port = htons(PORT);
    m_Inf.sin_addr.s_addr = INADDR_ANY;
    if(bind(m_Socket, (sockaddr*)(&m_Inf), sizeof(m_Inf)) == SOCKET_ERROR)
    {
        cout << "Cannot bind server socket!";
        WSACleanup();
        return 1;
    }
    if(listen(m_Socket, BACKLOG) == SOCKET_ERROR)
    {
        cout << "Server socket cannot start listening!";
        WSACleanup();
        return 1;
    }

    for(int i = 0; i < MAXCONN; i++)
    {
        m_Clients[i].SetSock(0);
    }

    cout << "Listening for connections..." << endl;
    pthread_t mThr;
    pthread_create(&mThr, NULL, AcceptClients, (void*)m_Socket);
    cin.ignore();
    cin.get();
    cin.clear();
    WSACleanup();
    return 0;
}

void *AcceptClients(void *arg)
{
    int m_Socket = (int)arg;
    while(1)
    {
        sockaddr_in Sin;
        int SinLen = sizeof(Sin);
        SOCKET c_Socket = accept(m_Socket, (sockaddr*)(&Sin), &SinLen);
        if(c_Socket == INVALID_SOCKET)
        {
            cout << "A connection initialized but dropped! (invalid socket)" << endl;
        }
        else
        {
            pthread_t hThr;
            pthread_create(&hThr, NULL, HandleClient, (void*)c_Socket);
        }
    }
    return 0;
}

void *HandleClient(void *arg)
{
    int inSock = (int)arg;
    bool avaibleFound = false;
    int lastLooked = 0;
    int avaibleAddr = -1;
    while(!avaibleFound)
    {
        avaibleFound = true;
        if(lastLooked != MAXCONN)
        {
            if(m_Clients[lastLooked].GetSock() == 0)
            {
                avaibleAddr = lastLooked;
                avaibleFound = true;
            }
            else
            {
                lastLooked += 1;
                avaibleFound = false;
            }
        }
        else
        {
            avaibleAddr = -1;
            avaibleFound = true;
        }
    }
    if(avaibleAddr != -1)
    {
        m_Clients[avaibleAddr].SetSockAddr(avaibleAddr);
        m_Clients[avaibleAddr].SetSock(inSock);
        cout << "Socket(#" << inSock << ") connected." << endl;
        pthread_t cThr;
        pthread_create(&cThr, NULL, &Client::Listen, (void*)&m_Clients[avaibleAddr]);
    }
    else
    {
        send(inSock, "11", 2, 0);//11: Server is full!
        closesocket(inSock);
    }
    return 0;
}

void *DropClient(void *arg)
{
    int inSock = (int)arg;
    cout << "Socket(#" << inSock << ") disconnected." << endl;
    return 0;
}

void *ProcessData(void *arg)
{
    RecvDataModel *inData = (RecvDataModel*)arg;
    cout << inData->sockAddr << inData->inData << endl;
    delete inData;
    return 0;
}

私はすでにこのような質問を投稿しましたが、誰も答えませんでした。これは私にとって非常に重要です。申し訳ありません:L

4

1 に答える 1

0

listenへの呼び出しの直前に、関数に次を追加しますRecv

buffer[numBytes]=0;

このようにして、印刷しようとしている文字列がヌルで終了していることを確認し、初期化されていない文字列からのゴミがbuffer初めて表示されることはありません (はい、memset後でそれを行いますが、それは役に立ちません)。最初のパケット)。

于 2013-01-27T19:43:28.357 に答える