Отправка std :: map> через сокет C ++ (linux) - PullRequest
3 голосов
/ 20 мая 2019

Я пытаюсь отправить карту, состоящую из int и другой карты, через сокет TCP в linux.

карта имеет вид

map<int, map<string, double>>

После этой ТАКОЙ ссылки Я пытался сделать

unsigned char* mybytemap =  reinterpret_cast<unsigned char*>(&my_map);

Затем для отправки в буфер я использовал функцию write () следующим образом:

int size = sizeof(mybytemap);
char temp[10];
sprintf(temp, "%d", size);
write(sockfd, temp, strlen(temp));     //send the size for the client
write(sockfd, mybytemap, sizeof(mybytemap));

На стороне клиента:

char temp[10];
n  = read(sockfd, temp, 10);
size = stoi(temp);    //Got Size Of buffer

unsigned char * buf;
if(size != 0)
{
    buf = new unsigned char[size];
    int current=0;
    while(current<size)
    {
        n = read(sockfd,(unsigned char*)(buf)+current, min(1024,size-current));
        if (n <= 0)
        {
            cout<<"ERROR reading from socket when receiving"<<endl;
            break;
        }
        current+=n;
    }
}

map<int, map<string, double>> *test = reinterpret_cast< map<int, map<string, double>>* > (buf);

vector<int> ks;
for(map<int, map<string, double>>::iterator it = test->begin(); it != test->end(); ++it)
{
    ks.push_back(it->first);
    cout<<"id: "<<it->first<<endl;
}

но карта не была получена правильно и код сбоя при попытке доступа к данным. как это исправить?

Нужно ли мне XML карту? и если да, то может ли кто-нибудь подсказать мне, как это сделать?

Ответы [ 2 ]

3 голосов
/ 20 мая 2019

ответ в ссылке на ваш вопрос не относится к карте (карта не под)

общая идея, как можно кодировать \ декодировать карту: кодировать размер карты, а затем для каждого ключа / значения кодировать размер ключа, затем кодировать ключ, затем кодировать размер значения, затем кодировать значение. В следующем коде предполагается, что вы кодируете size_t в sizeof (size_t) байтов

template<class T>
std::string encode(T value){
   // data to bytes
}

template<class T> 
T decode(std::string bytes){
  // bytes to data
}

template<class K, class V>
std::string encode_map(std::map<K, V> data){
  std::string result;
  result.append(encode<size_t>(data.size()));
  for(auto iter: data){
    std::string first = encode<K>(iter.first);
    result.append(encode<size_t>( first.size() ));
    result.append(first);
    std::string second = encode<V>(iter.second);
    result.append(encode<size_t>( second.size() ));
    result.append(encode<V>(iter.second));
  }
  return result;
}

template<class K, class V>
std::map<K, V> decode_map(std::string bytes){
  size_t index = 0;
  size_t size = decode<size_t>(std::string(bytes.begin()+index, bytes.begin()+index+sizeof(size_t) ) );
  index += sizeof(size_t);
  std::map<K, V> result;
  for(size_t i = 0; i<size; i++){
    size_t next_size = decode<size_t>(std::string(bytes.begin()+index, bytes.begin()+index+sizeof(size_t) ) );
    index += sizeof(size_t);
    K key = decode<K>(std::string(bytes.begin()+index, bytes.begin()+index+next_size ) );
    index += next_size;
    next_size = decode<size_t>(std::string(bytes.begin()+index, bytes.begin()+index+sizeof(size_t) ) );
    index += sizeof(size_t);
    V value = decode<V>(std::string(bytes.begin()+index, bytes.begin()+index+next_size ) );
    index += next_size;
    result[key] = value;
  }
  return result;
}
2 голосов
/ 20 мая 2019

В соответствии с рекомендациями необходимо выполнить так называемую сериализацию . Вы можете использовать Boost.Serialization в качестве библиотеки сериализации. Он может обрабатывать все типы STL. Наглядный пример:

std::map<int, std::map<std::string, double>> m1;
// ... (fill m1)

// serialize into a buffer (string):
std::string buffer;
boost::iostreams::back_insert_device<std::string> inserter(buffer);
boost::iostreams::stream<boost::iostreams::back_insert_device<std::string>> ostr(inserter);
boost::archive::binary_oarchive oa(ostr);
oa << m1;
ostr.flush();

// ... (here you can send the contents of buffer as plain bytes-chars via socket)

// deserialize into new map:
boost::iostreams::basic_array_source<char> device(buffer.data(), buffer.size());
boost::iostreams::stream<boost::iostreams::basic_array_source<char>> istr(device);
boost::archive::binary_iarchive ia(istr);
std::map<int, std::map<std::string, double>> m2;
ia >> m2;

Полная живая демонстрация (со всеми заголовками): https://wandbox.org/permlink/NyZeVTrFI0p8RcmY

...