Russian Qt Forum
Ноябрь 23, 2024, 12:05 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QUdpSocket прием и передача пакетов  (Прочитано 33703 раз)
onlik
Гость
« : Февраль 02, 2009, 16:33 »

Здравствуйте,

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

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

Спасибо.
« Последнее редактирование: Февраль 02, 2009, 16:37 от onlik » Записан
Dendy
Гость
« Ответ #1 : Февраль 02, 2009, 16:40 »

$QTDIR/examples/network/broadcastsender
$QTDIR/examples/network/broadcastreceiver
Записан
onlik
Гость
« Ответ #2 : Февраль 02, 2009, 16:46 »

Да, но там примеры не то что мне нужно... там реализовано вообще вещание...
Уже разобрался наверное...
Записан
onlik
Гость
« Ответ #3 : Февраль 02, 2009, 18:56 »

Нет, не работает Грустный
прошу вашей помощи!
Записан
onlik
Гость
« Ответ #4 : Февраль 02, 2009, 19:50 »

Возможно вопрос поставил не совсем понятно.

Есть клиент, есть сервер... нужно что бы клиент отправил пакет на сервер, а сервер в ответ клиенту... реализовать через QUdpSocket.
Записан
GDV1981
Гость
« Ответ #5 : Январь 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?
Записан
BRE
Гость
« Ответ #6 : Январь 25, 2010, 13:50 »

Где bind у client?
Записан
GDV1981
Гость
« Ответ #7 : Январь 25, 2010, 14:03 »

То есть без этого никак?

И если никак, то bind c какими параметрами должен быть вызван?
Код:
client->bind(QHostAddress("192.168.0.10"), 4321)
или
Код:
client->bind(QHostAddress("192.168.0.255"), 4321)
Записан
BRE
Гость
« Ответ #8 : Январь 25, 2010, 14:10 »

UDP протокол не устанавливает соединение, т.е. вбросили датаграмму в сеть и забыли.
Поэтому, если хочешь ловить датаграммы нужно делать bind.
Все клиенты равнозначны, т.е. параметры bind у всех будут одинаковыми.
Записан
GDV1981
Гость
« Ответ #9 : Январь 25, 2010, 14:25 »

Спасибо, я конечно догадывался, что дело как раз в этом, но верить хотелось в лучшее.. Улыбающийся

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

Записан
BRE
Гость
« Ответ #10 : Январь 25, 2010, 14:32 »

Спасибо, я конечно догадывался, что дело как раз в этом, но верить хотелось в лучшее.. Улыбающийся
Такое лучшее есть протокол tcp, который устанавливает соединение и обеспечивает двухсторонний канал.

А какой-нибудь rebind() клиента возможен?
Что значит rebind?
Записан
GDV1981
Гость
« Ответ #11 : Январь 25, 2010, 14:45 »

TCP - означает установку соединения. Клиент не знает, где в сети запущен сервер. Только поэтому TCP в моем случае не вариант.

rebind() - означает смену порта.
Дело в том, что если клиент будет отправлять датаграмму, то система автоматически присвоит следующий номер свободного порт.
А если теперь клиент вызовет метод bind() с другим портом, то ничего не получится.
Записан
BRE
Гость
« Ответ #12 : Январь 25, 2010, 14:49 »

TCP - означает установку соединения. Клиент не знает, где в сети запущен сервер. Только поэтому TCP в моем случае не вариант.
А такой вариант, клиент посылает по UDP датаграмму, сервер ее получает и отсылает ответную датаграмму, в которой сообщает все свои данные для подключения к нему по tcp... или сам организует соединение с клиентом.... или .... еще что-то подобное.  Улыбающийся
Записан
GDV1981
Гость
« Ответ #13 : Январь 25, 2010, 14:55 »

Цитировать
такой вариант, клиент посылает по UDP датаграмму, сервер ее получает и отсылает ответную датаграмму, в которой сообщает все свои данные для подключения к нему по tcp
Так и задумано.

Только не думал, что нужно и клиенту говорить bind()
Записан
pethead
Гость
« Ответ #14 : Ноябрь 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 можно перенести?
« Последнее редактирование: Ноябрь 01, 2010, 20:18 от pethead » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 21.