Типизация массива структур (указателей?) Для отправки через winsock - PullRequest
0 голосов
/ 06 февраля 2011

Я все еще разбираюсь в указателях и тому подобном, вот так ...

  • Каждый клиент правильно отправляет позицию игрока на сервер.
  • На сервере данные затем помещаются в массив структур (или указывают на структуры?).Данные этого массива также были проверены на правильность.
  • Затем сервер предназначен для отправки всех данных в этом массиве каждому из игроков
  • Я хотел бы иметь возможностьотправлять массивы с сервера клиенту (и обратно), так как именно этот подход я хочу использовать в своей голове, который я понимаю (или массивы указателей на структуры?), например массивы пуль и стрельбы, илидругие вещи.
  • Меня сейчас не беспокоит пропускная способность или оптимальный код, который приходит позже, когда я все лучше понимаю:)

По сути, я создал структурудля моего игрока: -

struct PlayerShip
{
    unsigned int health;
    unsigned int X;
    unsigned int Y;
};

Затем я создал массив (под руководством друзей), который позволяет мне получать доступ к данным этих структур (и вводить их по мере необходимости) (я думаю)

PlayerShip *playerArray[serverMaxClients];
for (int i = 0; i < serverMaxClients; i++)
{
    playerArray[i] = new PlayerShip;
    ZeroMemory(playerArray[i],sizeof(PlayerShip));
}

Я получаю данные от всех подключенных игроков и подаю их в массив

for (int slotIndex = 0; slotIndex < serverMaxClients; slotIndex++)
{
    char szIncoming[1500];
    ZeroMemory(szIncoming,1500);
    int connectionStatus = recv(clientSocketArray[slotIndex], (char*)szIncoming,sizeof(szIncoming),0);

    playerDataTemp = (PlayerShip*)szIncoming;
    playerArray[slotIndex]->X = playerDataTemp->X;
    playerArray[slotIndex]->Y = playerDataTemp->Y;
}

Я распечатываю массив, и все данные верны.

ИтакСледующим шагом является отправка этих данных баCK к клиенту.

Я попробовал следующее и несколько его вариантов, но я либо получаю ошибки компиляции, когда я пытаюсь изменить переменные в ссылки и / или указатели (у меня до сих пор не было этого явления прозрениягде указатели и ссылки вдруг имеют смысл), или значение выходит неправильно.(в приведенном ниже случае в настоящее время выводится неверное значение)

     for (int i = 0; i < serverMaxClients; i++)
     {
         char* outgoing = (char*)playerArray;

         if (clientSlotTaken[i] == true)
         {
              send(clientSocketArray[i],outgoing,sizeof(playerArray),0);
         }

         int *valueCheck;
         valueCheck = (int*)outgoing;
         cout << "VALUE CHECK " << valueCheck << "\n";

         delete outgoing;
     }

«Проверка значения», я ожидаю, будет «100», поскольку это должно быть здоровье игрока 1 из 100, которое было отправлено на сервер ранее.


ОБНОВЛЕНИЕ

Хорошо, теперь я начинаю думать об этом немного подробнее.

playerArray - массив указателей на структуры.Поэтому я не хочу отправлять необработанные данные из массива клиентам.Я хочу отправить данные о структурах игрокам.

Так что я предполагаю, что у меня должен быть фрагмент кода, который создает массив символов, который я заполняю данными из всех структур игрока.

Я попробовал следующее, но ...

        char outgoing[120];
        PlayerShip *dataPopulator;
        dataPopulator = &outgoing[0];  //Start at the begining of the array

        for (int i=0; i < serverMaxClients; i++)
        {
            *dataPopulator = playerArray[i];
            dataPopulator++;
        }

Я получаю следующие ошибки

  • не могу преобразовать 'char *' в 'PlayerShip *' в назначении|
  • нет совпадения для 'operator =' в '* dataPopulator = playerArray [i]' |

Благодаря Joriki, это помогает мне понять это немного больше, но я все ещеесть способ пойти: \ Все еще читая множество веб-страниц, которые пытаются объяснить указатели и тому подобное

1 Ответ

1 голос
/ 06 февраля 2011
PlayerShip *playerArray[serverMaxClients];

объявляет массив serverMaxClients указателей, каждый из которых указывает на PlayerShip структуру.

Здесь

char* outgoing = (char*)playerArray;

вы ссылаетесь на адрес этого массива указателей, поэтому ваш вызов send отправит кучу указателей, что почти наверняка не то, что вы хотите. Также здесь

delete outgoing;

вы пытаетесь удалить этот массив указателей, который был размещен в стеке, а не из кучи, поэтому это может вызвать серьезные проблемы; также вы удаляете один и тот же указатель на каждой итерации.

Я думаю, что к тому, что вы собираетесь делать, ближе подходит:

     for (int i = 0; i < serverMaxClients; i++)
     {
         char* outgoing = (char*)playerArray [i];

         if (clientSlotTaken[i] == true)
         {
              send(clientSocketArray[i],outgoing,sizeof(PlayerShip),0);
         }

         int *valueCheck;
         valueCheck = (int*)outgoing;
         cout << "VALUE CHECK " << *valueCheck << "\n";

         delete outgoing;
     }

Это отправляет данные в структурах PlayerShip, а не только машинно-зависимые указатели, и освобождает память, выделенную в куче «новым PlayerShip», в отличие от массива указателей, выделенных на стек. Обратите внимание также на добавленную звездочку в операторе вывода для проверки значения; Вы выводили указатель вместо того, на которое указывает значение. (Даже если бы вы добавили звездочку, вы бы просто получили int первого указателя в массиве, а не значение здоровья в структуре PlayerShip, на которую он указывает.)

Надеюсь, это поможет; не стесняйтесь задавать дополнительные вопросы в комментариях, если я не дал ясно понять.

Обновление в ответ на комментарии и обновление ChiggenWingz:

Если вы хотите отправить все данные каждому клиенту, я вижу три варианта:

1) Вы можете заменить send в моем коде на цикл:

    if (clientSlotTaken[i] == true)
    {
        for (int j = 0;j < serverMaxClients;j++)
            send(clientSocketArray[i],(char*)playerArray [j],sizeof(PlayerShip),0);
    }

Но я предполагаю, что вы пытаетесь избежать этого, поскольку это может сделать ввод-вывод менее эффективным.

2) Вы можете делать то, что пытались сделать в своем обновлении. Чтобы устранить перечисленные ошибки и заставить их работать:

a) Вам нужно разыграть char * на PlayerShip *, точно так же, как вам пришлось разыграть другой код в предыдущем коде.

b) В задании на копирование у вас есть PlayerShip слева, но PlayerShip * справа - вам нужно разыменовать этот указатель.

в) Использование фиксированной длины, такой как 120, довольно опасно; если у вас будет больше клиентов позже, это может переполниться; размер должен быть serverMaxClients * sizeof (PlayerShip).

d) "& outgoing [0]" является синонимом слова "outgoing".

Собираем все вместе:

    char outgoing[serverMaxClients * sizeof (PlayerShip)];
    PlayerShip *dataPopulator;
    dataPopulator = (PlayerShip*) outgoing;  //Start at the begining of the array

    for (int i=0; i < serverMaxClients; i++)
    {
        *dataPopulator = *playerArray[i];
        dataPopulator++;
    }

3) На мой взгляд, лучший вариант - разместить все PlayerShips вместе в одном смежном массиве, а не по отдельности. Вы можете сделать это либо в стеке, либо в куче, если хотите:

а) В куче:

PlayerShip *playerShips = new PlayerShip [serverMaxClients];
ZeroMemory (playerShips,serverMaxClients * sizeof(PlayerShip));

б) В стеке:

PlayerShip playerShips [serverMaxClients];
ZeroMemory (playerShips,sizeof(playerShips));

(вызов ZeroMemory в a) также будет работать в b), но не наоборот.)

Теперь, независимо от того, как вы распределили непрерывный массив, вы можете записать все данные каждому клиенту следующим образом:

 for (int i = 0; i < serverMaxClients; i++)
     if (clientSlotTaken[i] == true)
          send(clientSocketArray[i],(char *) playerShips,serverMaxClients * sizeof(PlayerShip),0);

(Опять же, в случае b) вы можете заменить вычисление размера на sizeof (playerShips).

Я надеюсь, что это прояснит ситуацию дальше - но не стесняйтесь задавать более общие вопросы об указателях, если вы все еще в замешательстве: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...