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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Чат клиент-сервер на блокирующих UDP сокетах.  (Прочитано 9035 раз)
Silver_swift
Гость
« : Февраль 24, 2011, 09:40 »

Всем привет!

Мне нужно сделать чат с клиентской и серверной частями с использованием блокирующих UDP сокетов. Это задание на лабораторной инсте поэтому нужно сделать именно так.

Проблема в том, что я в Qt новичок (где-то второй месяц читаю книгу Макса Шлее), знания С++ у меня есть и в принципе из того, что я читаю мне все более-менее понятно. Я просто физически не успею освоить всю книгу к сроку сдачи лабораторных. Потому прошу помощи.

Мне нужны Ваши советы по следующим вопросам:
1. Какой виджет лучше использовать для отображеня принятых сообщений, а какой для списка пользователей?
2. Как вообще реализовать передачу сообщения?
То есть я худо-бедно представляю как сделать интерфейс и могу создать объект QUdpSocket и что-то в него писать/читать.
Но я не очень представляю как лучше "подружить" интерфейс и сокет при том, что сокет и интерфейс должны создаваться в разных потоках (чтобы при использовании сокета интерфейс не подвисал или есть другие способы избежать подвисания?).
И я не знаю как сделать сокет блокирующим.

Вроде пока больше трудностей не возникло, но по мере выполнения работы буду что-то добавлять.

P.S. Поймите правильно только, мне не надо готовых кодов. Мне нужно чтобы вы помогли разобраться с тем, что мне не понятно и подсказали какие классы и методы лучше использовать для моих нужд ибо я просто не успеваю во всем разобраться. А как что реализовывать я посмотрю в справке, если чего не пойму снова к вам обращусь Улыбающийся

Очень надеюсь на понимание и поддержку сообщества. Не дайте  программисту во мне умереть Улыбающийся
Записан
Ubuntu_linux
Гость
« Ответ #1 : Февраль 24, 2011, 11:31 »

 Для сообщений  используй QPlainTextEdit.
Для списка юзеров используй QListWidget.
Пример клиент-сервер посмотри в асистенте, там проще некуда... или полязь на форуме, тут много примеров.
А что имеется под  блокировкой ?
Записан
Silver_swift
Гость
« Ответ #2 : Февраль 24, 2011, 12:44 »

Если создать блокирующий сокет в С,  то  когда выполняется чтение или запись все другие операции будут блочиться, пока не закончится чтение/запись. Поэтому если использовать sys/socket.h или winsock.h, надо создавать сокет в отдельном потоке.
А в Qt будто бы по умолчанию создается не блокирующий сокет. Что-то вроде того...

Может надо какой-то другой конструктор использовать для блокирующего сокета или еще чего?

В примере чат сделан все в одной проге мне пока тяжко разбираться в коде. Буду мучить дальше.
Записан
Igore
Гость
« Ответ #3 : Февраль 24, 2011, 18:50 »

Если будешь использовать waitForConnected, waitForBytesWritten, waitForReadyRead то это будет блокирущее обращение к сокету, если программу организовать на signal -> slot, то будут не блокирующие signal -ы (connected, error, readyRead) и т.д.
« Последнее редактирование: Февраль 24, 2011, 18:52 от Igore » Записан
Ubuntu_linux
Гость
« Ответ #4 : Февраль 24, 2011, 19:02 »

 Так используй метод
 bool QObject::blockSignals ( bool block )
чтоб заблокировать сигнал от(к) сокета.

или чтоб дождатся завершения какого-то процеса.

QEventLoop loop;
    connect(SameProcess,SIGNAL(SameSignal),&loop,SLOT(quit()));
    loop.exec();
Записан
Silver_swift
Гость
« Ответ #5 : Февраль 24, 2011, 23:49 »

Спасибо за участие!

Возник вопрос.
Пока чат был одной программой все было более менее нормально и он даже отсылал сам себе сообщения. Но стоило разделить программу на клиента и сервера как возник затык.
Подозреваю что затык в 3 строчке:
Код:
Socket=new QUdpSocket (this);
quint16 Port=7777;
Socket->bind(Port)
Ибо программа запущенная второй просто не может выполнить bind() - порт уже занят.
На С в sys/socket.h сервер присваивал сокету адрес, а клиент подключался к нему вызовом connect(). Только в Qt connect это совсем не то. Встает вопрос: как быть? Непонимающий


Записан
Silver_swift
Гость
« Ответ #6 : Февраль 25, 2011, 09:16 »

Глупость вчера написал. Не должно быть в udp никакого вызова connect(). В udp соединение не устанавливается. Просто убрал bind из клиентской части. Использую readDatagram и writeDatagram. Сообщения отправляются клиентом, читаются на сервере и отправляются клиенту, но до клиента не доходят.
В чем может быть причина?
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Февраль 25, 2011, 10:02 »

Цитировать
В чем может быть причина?
В том, что UDP не гарантирует доставку, или у вас где-то ошибка.
Записан

ArchLinux x86_64 / Win10 64 bit
Silver_swift
Гость
« Ответ #8 : Февраль 26, 2011, 21:29 »

Пакеты не теряются. Я ж через loopback пока проверяю.

Ошибка наверняка где-то есть и заключается в неправильном использовании QUdpSocket.

Создаю объект QUdpSocket, присваиваю ему адрес и порт. Могу в этот сокет писать, могу из него читать по сигналу readyRead(). В клиентской программе присвоить тот же порт сокету я не могу иначе при запуске двух программ будет конфликт. Но (!) без выполнения bind() из сокета ничего не читается. Из этого два вывода:
- либо для сокетов без присвоенных имен нельзя использовать readyRead()
- либо для таких сокетов нельзя использовать readDatagram()

На этот вопрос я самостоятельно ответа не нашел. Посему прошу ответить вас, если можно.

Тупо сделал сокеты для клиента и сервера на разных портах. Работать работает, но это корявый способ. Кто-нибудь может растолковать как в Qt сделать так чтоб можно было использовать сокет на чтение и запись с двух концов?

edited:
Делаю что-то вроде этого:
  
Код:
  ClientSocket=new QUdpSocket (this);
    cport=new quint16;
    *cport=7777;
    ClientSocket->bind(*Adr,*cport);
    connect(ClientSocket,SIGNAL(readyRead()),this,SLOT(readUDP()));

Код:
void client::readUDP()
{
quint16 port;
ClientSocket->readDatagram(Data->data(),Data->size(),Adr,&port);
useData(Data->data());
}
« Последнее редактирование: Февраль 26, 2011, 21:35 от Silver_swift » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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