0

私はプロジェクトに取り組んでいますが、これで頭が痛いです。「 enet 」というネットワークライブラリを使っていて、情報をつなぐクライアントを割り当てようとしています。サイトのチュートリアルを使用して、次を使用しますserver.event.packet->data = "client info";。ビルド ログは次のとおりです (clang++ を使用してコンパイル):

./network.h:9:14: warning: in-class initialization of non-static data member accepted as a C++11 extension [-Wc++11-extensions] int clients = 0; ^ main.cpp:142:28: error: assigning to 'enet_uint8 *' (aka 'unsigned char *') from incompatible type 'const char [12]'; server.event.packet->data = "client info"; ^ ~~~~~~~~~~~~~

考えられるすべてのタイプのキャストを試し、検索しましたが、何も機能しないようです。私はくそったれを幸せにすることはできません。

Main.cpp:

#include <iostream>
#include <string>
#include <sstream>
#include <istream>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <stdio.h>
#include "network.h"
#include "clients.h"
#include "config.h"

void runCommand(std::string command);
int startNetwork();
void shutdownNetwork();
void addClientRecord();
std::string getUsername();

std::string username;

bool manualInput = false;
bool debug = true;

int iPeerCount = 0;

Server server;

int main(int argc, char ** argv){
    std::string currentCommand;

    if(manualInput==true){
        std::cout << "Please type a command: ";
        std::getline(std::cin,currentCommand);
        if(debug == true){
            std::cout << currentCommand << std::endl;
        }
        runCommand(currentCommand);
    }

    startNetwork();

    atexit(shutdownNetwork);

    return 0;
}

int startNetwork(){
    if (enet_initialize () != 0){
        std::cout << "\nAn error has occured while initializing ENet.\n";
        return EXIT_FAILURE;
    }
    server.startServer();
    return 1;
}

void shutdownNetwork(){
    enet_deinitialize();
}

int Server::startServer(){

//  server.serverOne = enet_host_create (& server.address, 32, 2, 0, 0);

//  if(CUSTOM_HOST == true){
//      enet_address_set_host(&address, HOST);
//  } else {
    server.address.host = ENET_HOST_ANY;
//  }
    server.address.port = PORT;

    server.serverOne = enet_host_create( & server.address, 32, 2, 0, 0);

        if(debug==true){
                printf("[NETWORK] Host: %x \n[NETWORK] Port: %u\n", server.address.host, address.port);
        }

    if(server.serverOne==NULL){
        std::cout << "\nAn error has occured while starting the ENet server.\n";
        exit (EXIT_FAILURE);
    }

    monitor();
    return 1;
}


void Server::monitor(){
    int clients = 0;
    if(debug==true){
        printf( "[NETWORK] Waiting for commands...\n" );
    }
    printf("[NETWORK] Server online, awaiting commands and/or connections...\n");
    scan_network:
    while(enet_host_service (serverOne, & event, 1000) > 0){
        switch(event.type){
            case ENET_EVENT_TYPE_CONNECT:
                clients++;
                printf("[INFO] New connection from: %x:%u.\n", event.peer -> address.host, event.peer -> address.port);
                addClientRecord();
    /*          for(int x=0;x<32;x++){
                    if(clients[x].name != ""){ }
                    else{
                        clients[x].name = "full";
                    }
                }*/
                break;
            case ENET_EVENT_TYPE_RECEIVE:
                if(debug==true){ printf("A packet of length %lu containing %s was received from %s on channel %u.\n", event.packet -> dataLength, event.packet -> data, event.peer -> data, event.channelID); }
                runCommand(reinterpret_cast<const char*>(event.packet -> data));
                enet_packet_destroy(event.packet);
/*              printf("Disconnect client %s ? ", event.peer -> data);
                gets(buffer);
                std::cout<<buffer<<std::endl;
                if(buffer=="yes"){
                    enet_peer_disconnect(event.peer, 0);
                }*/   //Do not use until fixed or spam!
                break;
            case ENET_EVENT_TYPE_DISCONNECT:
                clients--;
                printf("%s disconnected.\n", event.peer -> data);
                event.peer -> data = NULL;
            case ENET_EVENT_TYPE_NONE:
                break;
        }
    }
    goto scan_network;
}

void runCommand(std::string command){
    if((command == "disconnect") || (command == "Disconnect") || (command=="DISCONNECT")){
        enet_peer_disconnect(server.event.peer,0);
        printf("[INFO] Client %s issued the disconnect command.\n", server.event.peer -> data);
    }
}

std::string getUsername(){
    return username;
}

void addClientRecord(){
    std::string bufferName = ("client " + server.clients);
    server.event.packet->data = "client info";
}

Network.h:

#include <enet/enet.h>

class Server {
    public:
    ENetAddress address;
    ENetHost * serverOne;
    ENetEvent event;

    int clients = 0;

    int startServer();
    void monitor();
};

どんなアイデアや助けも大歓迎です。乾杯!

4

1 に答える 1

0

私が見る限りserver、タイプの構造体でServer、そのフィールドeventENetEventであり、そのフィールドpacketはタイプ_ENetPacket*であり、そのフィールド データはunsigned char*です。スタック上に сstring を作成し、最初の要素のアドレスをdataグローバルオブジェクトのフィールドに割り当てます。その後、関数を残して、そこに格納されたデータが利用できなくなってもポインターはまだ生きています。そのため、正しいタイプキャストを に使用すると segfault が発生しますunsigned char*。したがって、次のことを行う必要があります。

void addClientRecord()
{
  std::string bufferName = ("client " + server.clients);
  char* clientName = "client info";
  // Allocate mem
  char* data = new unsigned char[strlen(clientName)];
  // Copy string there
  strcpy(data, clientName);
  // Store pointer
  server.event.packet->data = (unsigned char*)data;
}

割り当てられたメモリをクリアすることを忘れないでください。つまり、server.event.packet->datanullptr 以外の値が含まれているかどうかを常に確認し、含まれている場合は削除してから割り当てる必要があります。また、存在する場合はその文字列を削除する場所のデストラクタとServer、開始時に nullptr を書き込むコンストラクタを提供する必要があります。これにより、ほとんどの場合、クラッシュにつながるごみのアドレスを削除することはありません。ただし、まず、クラスが上記の機能を提供するかどう_ENetPacketかを判断する必要があります。これがcstringの仕組みです。ENetEventdata

charPSデフォルトで無署名に切り替わるコンパイラフラグが必要です。

于 2014-03-22T08:45:40.577 に答える