Russian Qt Forum

Qt => Работа с сетью => Тема начата: lolbla2 от Февраль 14, 2012, 18:52



Название: [НЕ РЕШЕНО] Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: lolbla2 от Февраль 14, 2012, 18:52
Проблема в следующем: когда оба игрока двигаются или выполняют какие-то действия всё норм, но когда один ничего не делает,а другой например едет, то почему-то у того кто ничего не делает противоположный игрок передвигается рывками, то есть ощущение будто пинг ужасный, хотя на самом деле это не так, ведь когда оба двигаются у всех всё нормально. Я подумал дело в сервере? Хотя может и проблема в клиентах.

Игра состоит из серверного приложения и клиентского. Оба клиента передают инфу серверу, а сервер уже от 1 игрока передает инфу 2 игроку, а от 2-го наоборот 1-му.  Помогите кто знает как решить траблу....
Вот исходник сервера:
Структура Input
Код:
struct Input
{
   bool startflag;
   int player;
    bool t_dead;
    int t_dir;
    int t_posx;
    int t_posy;
    int t_movex;
    int t_movey;
    int b_posx;
    int b_posy;
    int b_dir;
};
На самом деле здесь есть ненужные переменные, потом их уберу, но пока дело не в этом.

Код:
struct PlayerInfo
{
    int players;
    int myPlayerNum;
};

const int startPos[6][2]={{400,400},{0,0}, {400,200} , {200,150}, {600,350}, {300,300}   };

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    setupUi(this);
    server = new QTcpServer(this);
    socket1 = new QTcpSocket(this);
    socket2 = new QTcpSocket(this);
    connect(server, SIGNAL(newConnection()), this , SLOT(OnClientConnected()));
    server->setMaxPendingConnections(2);
    players=0;
    server->listen(QHostAddress::Any);
    label->setText(MyIp::GetMyIp()+":"+QString::number(server->serverPort()));

    player1 = new Input;
    player2 = new Input;
    player1->t_posx = 400;
    player1->t_posy = 400;
    player1->t_dir = 1;
    player1->t_dead = false;
    player2->t_posx = 0;
    player2->t_posy = 0;
    player2->t_dir = 1;
    player2->t_dead = false;
}

void Widget::OnClientConnected()
{
    players++;
    QMessageBox::information(this,"connection!","client connected!");
    switch(players)
    {
    case 1:
        socket1 = server->nextPendingConnection();
        connect(socket1, SIGNAL(readyRead()), this, SLOT(OnReceiveData()));
        connect(socket1, SIGNAL(disconnected()), this, SLOT(OnClientDisconnected()));
        this->listWidget->addItem(socket1->peerAddress().toString()+":"+QString::number(socket1->peerPort()) );
        break;
    case 2:
        socket2 = server->nextPendingConnection();
        connect(socket2, SIGNAL(readyRead()), this, SLOT(OnReceiveData()));
        connect(socket2, SIGNAL(disconnected()), this, SLOT(OnClientDisconnected()));
        this->listWidget->addItem(socket2->peerAddress().toString()+":"+QString::number(socket2->peerPort()) );
        break;
    default:
//        server->nextPendingConnection()->abort();
        players--;
        QMessageBox::information(this,"disconection!","client disconected because already 2 players!");
    }

}

void Widget::OnClientDisconnected()
{
   if (socket1->state()!=QAbstractSocket::ConnectedState)
       this->listWidget->takeItem(0);
   if(socket2->state()!=QAbstractSocket::ConnectedState)
       this->listWidget->takeItem(1);
   players--;
}

void Widget::OnReceiveData()
{
    while(socket1->bytesAvailable())
        socket1->read((char*)player1,sizeof(*player1));
    while(socket2->bytesAvailable())
        socket2->read((char*)player2,sizeof(*player2));
    SendData();

}

void Widget::SendData()
{
    socket1->write((char*)player2,sizeof(*player2));
    socket2->write((char*)player1,sizeof(*player1));
    player1->b_posx = -1;
    player1->b_posy = -1;
    player2->b_posx = -1;
    player2->b_posy = -1;

}

void Widget::SendPlayerInfo()
{
    PlayerInfo *info= new PlayerInfo;
    info->players=players;
    info->myPlayerNum=1;
    socket1->write((char*)info, sizeof(*info));
    info->myPlayerNum=2;
    socket2->write((char*)info, sizeof(*info));

}

void Widget::on_pushButton_clicked()
{
    if(players!=2)
        QMessageBox::information(this,"Fail","Can't start the game with 1 player!");
    else
        SendPlayerInfo();
}


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: Bepec от Февраль 15, 2012, 08:39
А можно проектик? Хоцца посмотреть и поиграться :D


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: SimpleSunny от Февраль 15, 2012, 12:28
1. Удалите из конструктора, это лишнее.
socket1 = new QTcpSocket(this);
socket2 = new QTcpSocket(this);

2. Неправильно читаете данные
while(socket1->bytesAvailable())
socket1->read((char*)player1,sizeof(*player1));

2.1 Нет гарантии, что пришли все данные, надо проверять это
if (socket1->bytesAvailable() >= FRAME_SIZE)
in >> player1;
2.2 Нельзя так читать данные напрямую в структуру, проблема может быть из-за разных Endians, выравнивания. Используйте лучше QDataStream.

3. write аналогично сделать через QDataStream

4. Установите для сокета LowDelayOption 1. После write делайте flush.


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: lolbla2 от Февраль 15, 2012, 13:36
1. Удалите из конструктора, это лишнее.
socket1 = new QTcpSocket(this);
socket2 = new QTcpSocket(this);

2. Неправильно читаете данные
while(socket1->bytesAvailable())
socket1->read((char*)player1,sizeof(*player1));

2.1 Нет гарантии, что пришли все данные, надо проверять это
if (socket1->bytesAvailable() >= FRAME_SIZE)
in >> player1;
2.2 Нельзя так читать данные напрямую в структуру, проблема может быть из-за разных Endians, выравнивания. Используйте лучше QDataStream.

3. write аналогично сделать через QDataStream

4. Установите для сокета LowDelayOption 1. После write делайте flush.

У меня раньше было через этот QDataStream, но было так что Input player1; то есть не ссылка, а сам объект и потом там всякие проверки как в примере ну и in>>player1; при этом ещё медленее работало

Надо ссылку на объект в датастрим пихать тоесть Input *player1 ?


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: SimpleSunny от Февраль 15, 2012, 15:13
Честно говоря не понял о чем вы.
Код
C++ (Qt)
operator<<(QdataStream &out, const Input &input)
{
out << input.startflag << input.player << input.t_dead >>...;
return out;
};
operator>>(QdataStream &in, Input &input)
{
in  >> input.startflag >> input.player >> input.t_dead >>...;
return in;
};

Иcпользовать так
Код
C++ (Qt)
Input input;
QdataStream out(socket);
out << input;


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: lolbla2 от Февраль 15, 2012, 15:28
Честно говоря не понял о чем вы.
Код
C++ (Qt)
operator<<(QdataStream &out, const Input &input)
{
out << input.startflag << input.player << input.t_dead >>...;
return out;
};
operator>>(QdataStream &in, Input &input)
{
in  >> input.startflag >> input.player >> input.t_dead >>...;
return in;
};

Иcпользовать так
Код
C++ (Qt)
Input input;
QdataStream out(socket);
out << input;

Я уже так пробовал делать, ещё хуже тормозило, поэтому подумал может надо
Иcпользовать так
Код
C++ (Qt)
Input *input= new Input;
QdataStream out(socket);
out << input;

Возможно так быстрее будет работать или не влияет?


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: SimpleSunny от Февраль 15, 2012, 16:30
Не влияет.


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: lolbla2 от Февраль 15, 2012, 20:29
Не влияет.

 просто у меня раньше через QDataStream было и ещё хуже тормозило, вот и делай выводы...


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: merke от Февраль 16, 2012, 19:05
Не влияет.

 просто у меня раньше через QDataStream было и ещё хуже тормозило, вот и делай выводы...

Что за бред, ни чего не будет тормозить, перестрой структуру сервера, используй только датастрим и будет тебе счастье.


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: lolbla2 от Февраль 17, 2012, 05:43
Не влияет.

 просто у меня раньше через QDataStream было и ещё хуже тормозило, вот и делай выводы...

Что за бред, ни чего не будет тормозить, перестрой структуру сервера, используй только датастрим и будет тебе счастье.
На клиенте тогда ведь тоже через датастрим надо?

Да до этого было с датастримом просто, потом переделал не через датастрим быстрее стало работать


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: SimpleSunny от Февраль 17, 2012, 12:03
На клиенте тоже через datastream.
Задержки, если и появляются, то из-за кривого сервера\клиента, но не из-за datastream.


Название: Re: Танчики на 2 игроков по сети. ПРоблема с сервером.
Отправлено: lolbla2 от Февраль 17, 2012, 18:46
Не знаю тогда почему с socket1->read((char*)player1,sizeof(*player1)); и socket1->write((char*)player1,sizeof(*player1)); быстрее работает, может потому что в QDataStream ещё много всего нагружено...