Я работал над проектом, и мальчик, о, мальчик, у меня болит голова от этого. Я использую сетевую библиотеку под названием «ENET«и я пытаюсь назначить клиента, который подключает информацию. Используя учебник на сайте, я использую: server.event.packet->data = "client info";
Однако enet жалуется, что строка не является «беззнаковым символом *». Вот журнал сборки (используя 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();
};
Любые идеи и помощь очень ценятся. Ура!
Насколько я вижу server
это структура типа Server
, его поле event
является ENetEvent
и его поле packet
имеет тип _ENetPacket*
и его полевые данные являются unsigned char*
, Итак, что происходит: вы создаете строку в стеке, а затем назначаете адрес первого элемента data
поле глобального объекта, затем вы покидаете функцию, и указатель остается живым, в то время как сохраненные там данные больше не доступны. Вот почему вы получаете segfault при использовании правильного Typecast для 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->data
содержит значение, отличное от nullptr, и, если оно есть, — удалить и только потом назначить. И вы должны предоставить деструктор для Server
где он удалит эту строку, если какой-либо подарок и конструктор запишут туда nullptr при запуске, чтобы вы не удалили какой-либо мусорный адрес, что наверняка приведет к сбою. Но прежде всего нужно выяснить, _ENetPacket
или же ENetEvent
классы предоставляют любую функциональность для data
упомянутое выше. Вот как работают cstrings.
Постскриптум Там должен быть флаг компилятора, который будет переключаться char
быть неподписанным по умолчанию.
Других решений пока нет …