-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* 格式,否则我什么都不懂!

现在我想问:字符串和字符的性能是一样的吗?使用字符串而不是char *(指针-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 回答