Qt4 vs #include <sys/socket.h> (Пересекаются(одинаковые) функции connect)

Модератор: Модераторы разделов

Аватара пользователя
creative
Сообщения: 136
ОС: openSuSE / Windows XP

Qt4 vs #include <sys/socket.h>

Сообщение creative »

У меня вопрос к тем, кто занимался программированием сокетов.
В Qt4 соединение сигналов и слотов происходит при помощи connect.
Если работать только на С++ с сокетами, то есть заголовочные файлы:

Код: Выделить всё

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


при помощи которых можно использовать технологию сокетов.

Технология сокетов используется вот так:

Код: Выделить всё

#include <stdio.h>
#include <iostream>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

int main(int nArg, char** pArgs)
{

    int mySocket = socket(PF_INET, SOCK_STREAM, 0);

    struct sockaddr_in serv_address;
    serv_address.sin_family = PF_INET;
    serv_address.sin_port = htons((u_short)1500);
    serv_address.sin_addr.s_addr = inet_addr("127.0.0.1");
    int i = connect(mySocket, (struct sockaddr *) &serv_address, sizeof(serv_address));

        write(mySocket, "Hello Server!", sizeof("Hello Server!"));

        char server_message[100];

    read(mySocket, server_message, sizeof(server_message));
    cout << server_message << "\n";

    close(mySocket);
    return 0;
}


Это простейший пример, написан клиент, подключающийся на петлю(127.0.0.1) на порт 1500. Вместо указания явного IP в случае использования на своем же компьютере можно использовать просто serv_address.sin_addr.s_addr = 0; но не в этом суть.

Суть в том, что как видите, здесь присутствует int i = connect(....
В Qt4 connect тоже используется.
При компиляции возникает вот такая вот ошибка:

Код: Выделить всё

nik@nik:~/NetBeansProjects/Cpp/ClientServer/simpleChatWithQt> qmake -project
nik@nik:~/NetBeansProjects/Cpp/ClientServer/simpleChatWithQt> qmake
nik@nik:~/NetBeansProjects/Cpp/ClientServer/simpleChatWithQt> make

*******
тут была информация о ходе создания moc файлов итд...
*******

MySocket.cpp: In member function ‘virtual void MySocket::run()’:
MySocket.cpp:35: error: no matching function for call to ‘[b]MySocket::connect(int&, sockaddr*, unsigned int)[/b]’
/usr/include/QtCore/qobject.h:197: note: [b]candidates are: static bool QObject::connect(const QObject*, const char*, const QObject*, const char*, Qt::ConnectionType)[/b]
/usr/include/QtCore/qobject.h:302: note:                 bool QObject::connect(const QObject*, const char*, const char*, Qt::ConnectionType) const
make: *** [MySocket.o] Ошибка 1
nik@nik:~/NetBeansProjects/Cpp/ClientServer/simpleChatWithQt>


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

Вот и главный вопрос:
Что мне делать?
Как сделать чтобы одна и та же фунция connect из разных библиотек не пересекалась?
Как устранить эту зависимость?



P.S.
я знаю что в Qt4 организованно кроссплатформенная поддержка сокетов, есть встроенные классы Qt4 работающие с сокетами, там всё удобно разложено по полочкам и вылизано до блеска. Но мне необходимо использовать системные библиотеки <sys/types.h>, <sys/socket.h>, <netinet/in.h>, <arpa/inet.h>, т.к. преподаватель задал задание "Сделать простейший чат по технологии сокетов".
Делать консольный чат... 21й век, GUI процветают :-) Поэтому решил делать с использованием Qt4. И если я ему принесу писанное полностью на Qt4... Есть вероятность что он не поймёт Qt4. С другой стороны, если я ему в коде ткну пальцем и покажу где используется стандартные библиотеки, он поймет, увидев знакомые строчки, и поставит всё что мне нужно =)
Спасибо сказали:
MrSinister
Сообщения: 95

Re: Qt4 vs #include <sys/socket.h>

Сообщение MrSinister »

Не пробовал вызывать Qt'шную функцию указывая её область видимости: QObject::connect(/*аргументы*/); ?
Можно ещё попробовать ограничить область видимости Qt'шного класса.
namespace

Можно попробовать заюзать extern "C" int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);

creative писал(а):
16.04.2010 23:58
Делать консольный чат... 21й век, GUI процветают :-)

А вот можно сделать по *nix-way'ному: создать консольный чат и сделать его функции такими, чтобы можно при создании GUI просто вызывать их.

upd: C extern скомпилировалось при следующем использовании:

Код: Выделить всё

     extern int  connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
     int i = connect(mySocket, (struct sockaddr *) &serv_address, sizeof(serv_address));
     QObject::connect(/*аргументы*/);


/* эх, смешивать C и C++ код неэстетично, имхо) Я бы либо одно либо другое выбрал, благо имеется GTK для C и ещё всякие библиотеки. */
Спасибо сказали:
Аватара пользователя
creative
Сообщения: 136
ОС: openSuSE / Windows XP

Re: Qt4 vs #include <sys/socket.h>

Сообщение creative »

Спасибо, буду знать в какую сторону копать =)

можно сделать по *nix-way'ному: создать консольный чат и сделать его функции такими, чтобы можно при создании GUI просто вызывать их

да я и не спорю что можно, но у меня главная задача удовлетворить потребности преподавателя и показать ему то что он требует =) там чат ну самый простой какой только бывает =)
Вот так GUI выглядят:







т.е. здесь проще некуда. После подключения к какому-либо серверу программа будет работать пока не выключишь без возможности сделать реконнект на другой сервер, сам сервер при создании - нет возможности указать на каком порту он создаться, нет смайлов(зато есть RichText :gun: ), окошко с фиксированным размером, с обычными Layout'aми. В общем ну очень всё просто, конечная цель - использовать данные библиотеки, а не создать новую программу чат :blush:
Если по *nix-way'ному - нужно выпускать качественный продукт, а у меня он изначально не качественный, потому что только учусь в этой области :tongue:
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt4 vs #include <sys/socket.h>

Сообщение NickLion »

Чтобы вызвать connect для работы с сокетами используйте

Код: Выделить всё

int i = ::connect(mySocket, (struct sockaddr *) &serv_address, sizeof(serv_address));

(желательно и остальные функции работы с сокетами)
Это будет указанием компилятору использовать connect из глобальной области имён (А не из QObject). Или сокеты Qt использовать.
(Можно ещё попробовать завернуть #include <sys/socket.h> в namespace и использовать из него. Но это может не прокатить)

PS а, дочитал до конца, ну, тогда используйте :: - так будет проще всего. (или вынести функции по работе с сокетами в глобальные, не связанные с Qt, а из кода Qt классов вызывать эти глобальные функции, но это мороки больше)
Спасибо сказали:
Аватара пользователя
creative
Сообщения: 136
ОС: openSuSE / Windows XP

Re: Qt4 vs #include <sys/socket.h>

Сообщение creative »

Спасибо за мысль, вечером приду попробую через ::connect. После отпишусь.
Спасибо сказали:
Аватара пользователя
creative
Сообщения: 136
ОС: openSuSE / Windows XP

Re: Qt4 vs #include <sys/socket.h>

Сообщение creative »

Попробовал через ::connect
Всё получилось и работает. Спасибо :-)

В данный момент программа работает, наблюдаются пара крупных недочётов и багов в работе программы, но это не смертельные :-)
Один из багов такой - когда клиент отключается, то сервер почему-то заваливает последним отправленным с клиента сообщением в огромных количествах. Точнее так:

Код: Выделить всё

QString s;
char a[10000];
while(1)
{
       ::read(mySocket, a, sizeOf(a)); /*после откл. клиента эта строчка уже не функционирует и соответственно идёт бесконечное получения заранее сохраннённого значения s*/
       s = QString::fromLocal8bit(a);
       emit getMessage(s);
}


т.к. считывание в цикле, а цикл в потоке, то используется emit.
Пока клиент подключен цикл ждёт получения сообщения. Как только клиент отключился - идёт бесконечное emit поледнего входящего сообщения.

Вопрос - как отследить отключения клиента?

Были идеи такие:

Код: Выделить всё

While(mySocket>0)

Но не работает.

В общем программа работает на 70%. Для сдачи преподавателю подойдёт. Но для себя - хочется чтобы работала на 100%. ПОэтому буду разбираться с отключением сокета. Ещё не знаю как с listen работать. Пока программа сервер может иметь одного клиента и работает так:
на порту 1500 сервер ожидает подключения. После того как клиент подключился начинате работать чат. После того как клиетн отключился по идее сервер не должен отключаться. Сервер должен ждать следующего подключения. Но пока сервер просто виснет :-( Итого - нужно разобраться с listen и c отключкой клиента.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt4 vs #include <sys/socket.h>

Сообщение NickLion »

creative писал(а):
18.04.2010 22:23
Вопрос - как отследить отключения клиента?

Проверить возвращаемое ::read значение. 0 - сигнализирует об отключении.
А чтение у Вас блокирующее? Вроде бы read не гарантирует, что будет считано точно указанное число байт. В общем, не знаю, может я не прав, но ИМХО стоит удостовериться, что пришло именно sizeof(a) байт, и если нет - дочитать хвост.

creative писал(а):
18.04.2010 22:23
Пока программа сервер может иметь одного клиента и работает так:…

При подключении нового клиента для него выделяют новый поток (ну, или fork) и работают с клиентом в нём. А в основном продолжают слушать. Так получится организовать одновременное подключение.
т.е. схема такая:
0.0. bind
0.1. listen
0.2. accept
0.3. fork/pthread_create --> 1.0
0.4. goto 0.2

1.0 x = 0, k = 0
1.1 x += k = read
1.2 если x == 0 kill-me
1.3 если k < 0, обработка ошибки, kill-me
1.4 если x < size, goto 1.1
1.5 process query
1.6 goto 1.0

вроде всё :)
Спасибо сказали:
Аватара пользователя
creative
Сообщения: 136
ОС: openSuSE / Windows XP

Re: Qt4 vs #include <sys/socket.h>

Сообщение creative »

Спасибо за советы. Сегодня попробую:
Проверить возвращаемое ::read значение

Это для начала, потом попробую с подключением потока по требованию.

Уже сейчас возникает стойкое ощущение, что и часть клиента, и часть сервера в программе придёться реорганизовывать. Конечно не с нуля делать, но брутально править.

Отнёс программку преподавателю... И столкнулся с интересной особенностью. До того как отнести преподавателю протестил на 6ти различных машинах. Везде стояла Suse версией >11. Всё работало(были исключения - на двух компах почему-то сервер на порт повесить не удавалось, чувствуется это так систему настроили, но клиентом на этих машинах подключаться к другому серверу можно было).
На машине преподавателя при запуске выдало ошибку. Дословно не помню, но суть в том, что при запуске не может обнаружить libQtGui библиотеку =-О. Думаю вопрос решается подбором такого метода компиляции, при котором эта библиотека будет утрамбована в конечный исполняемый файл. Конечно размер файла немножко(я на это надеюсь) увеличится.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Qt4 vs #include <sys/socket.h>

Сообщение NickLion »

creative писал(а):
20.04.2010 18:45
На машине преподавателя при запуске выдало ошибку. Дословно не помню, но суть в том, что при запуске не может обнаружить libQtGui библиотеку =-О. Думаю вопрос решается подбором такого метода компиляции, при котором эта библиотека будет утрамбована в конечный исполняемый файл. Конечно размер файла немножко(я на это надеюсь) увеличится.

Статическая линковка Qt. Не знаю насколько всё это просто. Размер увеличится ощутимо (несколько Мб пожалуй, но не буду гарантировать). А на компе преподавателя отсутствует Qt? А как компилить там предполагается? Или бинарник запустить? Может просто .so потащить?
Спасибо сказали:
Аватара пользователя
creative
Сообщения: 136
ОС: openSuSE / Windows XP

Re: Qt4 vs #include <sys/socket.h>

Сообщение creative »

Ээх, пока не успел осуществить задуманное =(
Ощутимо - несколько Мб... Ну нет, у нас в Университете не настолько древние машинки, чтобы пара мегабайт для них уже было ощутимо... да ещё и с такими толстыми каналами в сетях... Ну в общем это не будет особо ощутимо. Вот пара тройка сотен мегабайт уже ощутимо... для меня, но не для Университетских машин =)

Что самое интересное - как только программка не запустилась - я предложил перекомпилить её на компе преподователя. Использовали стандартное:

Код: Выделить всё

qmake -project
qmake
make


После такой комбинации по идее даже если библиотека libQtGui лежала в другом месте - всё должно было правильно собраться. Собралось без ошибок... Но с одним НО: после запуска снова жалуется на ту же самую libQtGui... :-) Замкнутый круг. Поэтому пока мысли - запихнуть всё что можно в бинарник. И бинарник уже запускать у преподователя.

*Отредактированно:
Всё-таки придётся перелопатить половину программки.
Спасибо сказали:
Аватара пользователя
chups
Сообщения: 79
ОС: Debian Lenny GNU/Linux

Re: Qt4 vs #include <sys/socket.h>

Сообщение chups »

может быть для топикстартера еще актуально:
статическая_сборка
по ссылке доки как собрать статическую qt4 и соответственно получить на выходе статическое приложение.
я когда-то под винды собирал - графическое приложение получалось порядка 10-ти метров. upx сжималось до 3-х.
Спасибо сказали:
Аватара пользователя
creative
Сообщения: 136
ОС: openSuSE / Windows XP

Re: Qt4 vs #include <sys/socket.h>

Сообщение creative »

да, пожалуй соглашусь, для топикстартера это действительно актуально. спасибо.
топикстартер как раз собирался в ближайшее время(желательно до сессии) освоить работу в винде - кроскомпиляция и статика.
на данный момент дело пока встало из-за острой нехватки времени.
Спасибо сказали: