C ++多个参数(带结构)char*发送错误(错误类型)?线程

c++ multiple arguments (with struct) char* send error (wrong type)? pthread

本文关键字:错误 类型 线程 char 参数 结构      更新时间:2023-10-16

答案:(因为我在 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);
}

我认为字符串会自动修复字符*格式,否则我什么都听不懂!

现在我想问:字符串和字符性能相同吗? 使用字符串而不是字符*(指针无效*-除外)是否有问题?

问题:-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来自这里(Client Class):

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

和所有主要.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

在调用 Recv 之前将以下内容添加到 listen 函数中:

buffer[numBytes]=0;

这样,您将确保您尝试打印的字符串以 null 结尾,并且您不会第一次看到来自未初始化buffer的垃圾(是的,您稍后memset它,但它对第一个数据包没有帮助)。