Russian Qt Forum

Qt => Работа с сетью => Тема начата: onlik от Февраль 02, 2009, 16:33



Название: QUdpSocket прием и передача пакетов
Отправлено: onlik от Февраль 02, 2009, 16:33
Здравствуйте,

Как мне реализовать обмено пакетами между двумя компьютерами?
Пока получается отправлять пакеты на сервер, а ответ получить не могу.
Буду благодарен за примеры или инфу.

Или это нельзя сделать одним сокетом? Т.е. как в QTcpSocket я подключаюсь к серверу и могу с ним обмениваться информацией.

Спасибо.


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: Dendy от Февраль 02, 2009, 16:40
$QTDIR/examples/network/broadcastsender
$QTDIR/examples/network/broadcastreceiver


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: onlik от Февраль 02, 2009, 16:46
Да, но там примеры не то что мне нужно... там реализовано вообще вещание...
Уже разобрался наверное...


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: onlik от Февраль 02, 2009, 18:56
Нет, не работает :(
прошу вашей помощи!


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: onlik от Февраль 02, 2009, 19:50
Возможно вопрос поставил не совсем понятно.

Есть клиент, есть сервер... нужно что бы клиент отправил пакет на сервер, а сервер в ответ клиенту... реализовать через QUdpSocket.


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: GDV1981 от Январь 25, 2010, 13:44
Доброго всем времени суток.
Не стал открывать новую тему, поскольку посчитал, что эта подойдет самым лучшим образом для моего вопроса.

Разрабатывается клиент-серверное приложение.
Не получается реализовать эхо-сервер на UDP.
Проблема следующая.
Запускается сервер:
Код:
server = new QUdpSocket();
server.bind(QHostAddress("192.168.0.255"), 12345);
connect(server, SIGNAL(readyRead()), SLOT(onServerReadyRead()));

После того как клиент отправил сообщение в свою подсеть на порт, который слушает сервер:
Код:
client = new QUdpSocket();
connect(client, SIGNAL(readyRead()), SLOT(onClientReadyRead()));
client->writeDatagram("Servers, where are you?", QHostAddress("192.168.0.255"), 12345 );

На сервере срабатывает сигнал readyRead.
Сервер читает датаграмму и при этом определяет откуда она была отправлена:
Код:
QHostAddress sender;
quint16 senderPort;
server->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);

Приняв датаграмму, сервер отправляет ее обратно клиенту:
Код:
server->writeDatagram(datagram.data(), datagram.size(), &sender, &senderPort);

Теперь вопрос. Какие танцы с бубнами надо совершить, чтоб у клиента сработал сигнал readyRead?


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: BRE от Январь 25, 2010, 13:50
Где bind у client?


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: GDV1981 от Январь 25, 2010, 14:03
То есть без этого никак?

И если никак, то bind c какими параметрами должен быть вызван?
Код:
client->bind(QHostAddress("192.168.0.10"), 4321)
или
Код:
client->bind(QHostAddress("192.168.0.255"), 4321)


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: BRE от Январь 25, 2010, 14:10
UDP протокол не устанавливает соединение, т.е. вбросили датаграмму в сеть и забыли.
Поэтому, если хочешь ловить датаграммы нужно делать bind.
Все клиенты равнозначны, т.е. параметры bind у всех будут одинаковыми.


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: GDV1981 от Январь 25, 2010, 14:25
Спасибо, я конечно догадывался, что дело как раз в этом, но верить хотелось в лучшее.. :)

А какой-нибудь rebind() клиента возможен?



Название: Re: QUdpSocket прием и передача пакетов
Отправлено: BRE от Январь 25, 2010, 14:32
Спасибо, я конечно догадывался, что дело как раз в этом, но верить хотелось в лучшее.. :)
Такое лучшее есть протокол tcp, который устанавливает соединение и обеспечивает двухсторонний канал.

А какой-нибудь rebind() клиента возможен?
Что значит rebind?


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: GDV1981 от Январь 25, 2010, 14:45
TCP - означает установку соединения. Клиент не знает, где в сети запущен сервер. Только поэтому TCP в моем случае не вариант.

rebind() - означает смену порта.
Дело в том, что если клиент будет отправлять датаграмму, то система автоматически присвоит следующий номер свободного порт.
А если теперь клиент вызовет метод bind() с другим портом, то ничего не получится.


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: BRE от Январь 25, 2010, 14:49
TCP - означает установку соединения. Клиент не знает, где в сети запущен сервер. Только поэтому TCP в моем случае не вариант.
А такой вариант, клиент посылает по UDP датаграмму, сервер ее получает и отсылает ответную датаграмму, в которой сообщает все свои данные для подключения к нему по tcp... или сам организует соединение с клиентом.... или .... еще что-то подобное.  :)


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: GDV1981 от Январь 25, 2010, 14:55
Цитировать
такой вариант, клиент посылает по UDP датаграмму, сервер ее получает и отсылает ответную датаграмму, в которой сообщает все свои данные для подключения к нему по tcp
Так и задумано.

Только не думал, что нужно и клиенту говорить bind()


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: pethead от Ноябрь 01, 2010, 19:54
я в дельфи делал так:
udp компонентом и посылал и ловил ответ. суть в чем. отправляем на фиксированный порт, а ставим на прослушку тот порт что дала винда ибо ктото еще с этого компа может общаться с сервером, тогда у обоих порт на прослушку свой и ответы приходят получателям клиентам- каждому свой ответ. и ставить в бинд фиксированный порт это не дело.
как сделать подобную схему на qt udp? может ReadWrite флаг какой то при передаче стрима в сокет? тогда ReadyRead сработает на прием после отылки запроса. нет?
еще вопрос: если делать 2-мя сокетами, то как получить входящий (исходящий порт фиксированый) порт с пишущего сокета чтобы воткнут его в бинд на читающем сокете?
щас у меня есть вариант на Си, на беркли-сокетах, через wsa, отсылаю запрос и тут же слушаю - получаю ответ. но хотел на Qt переделать :)
вот

S = socket(AF_INET,SOCK_DGRAM,0);

 SA.sin_family=AF_INET;
 SA.sin_port=htons(LMCP_REMOTE_PORT);
 SA.sin_addr.S_un.S_addr=inet_addr(_ip.c_str());


//отправка пакета
 if(sendto(S, (char*)sendbuf,sizeof(sendbuf), 0,(struct sockaddr *)&SA, sizeof(SA))<0)
 {
  iResult=WSAGetLastError();
  closesocket(S);
  WSACleanup();
  return 1;
 }

 //прием ответа
 //проверяем наличие данных в сокете, установив файловый дескриптор сокета в множестве "на чтение"
 fd_set rfds;

 struct timeval tv;    
 tv.tv_sec = _timeout;
 tv.tv_usec = 0;

 FD_ZERO(&rfds);
 //помещаем дескриптор сокета в множество "на чтение"
 FD_SET(S,&rfds);

 //контролируем активность сокета
 //если таймаут не успел завершиться
 if (select((int)S+1, &rfds, NULL, NULL, &tv) > 0)
 {
  //извлекаем данные из сокета
  iResult=recvfrom(S, (char*)recvbuf, recvbuflen, 0, (struct sockaddr *)&SA, &SA_Size);
  closesocket(S);
  WSACleanup();
такое на qt udp можно перенести?


Название: Re: QUdpSocket прием и передача пакетов
Отправлено: pethead от Ноябрь 02, 2010, 04:16
в ассистенте написано про вирт.коннект ConnectToHost и далее write\read. оно?
я в Qt не так силен еще, не все классы толком знаю.