
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.14.90] |
![]() |
|
Страницы: (5) « Первая ... 2 3 [4] 5 все ( Перейти к последнему сообщению ) |
Сообщ.
#46
,
|
|
|
Цитата Qraizer @ Совершенно несложно учесть разницу в конструкторах объектов-сокетах. Делов-то на один API-вызов. Но не сокетами ж едиными. Есть ещё файлы в $TEMP (...я бы так и вообще намутил basic_socketstream<> и натравил на std::(i|o|io)stream), eсть готовые библиотеки, если религия заказчик не возражает. Можно вполне и так. Если не учесть, что ранее macomics пацанов туманил относительно MSYS2 ![]() Цитата macomics @ Затем, что по заданию она должна компилироваться на linux. И вот тут косяк, если из-за как-то не учтенной особенности linux, не выученной своевременно, программа просто не сможет откомпилироваться. Вот элементарный пример. Для взаимодействия предложили использовать socket. Но на Windows для работы с socket надо использовать WSAStartup и WSACleanup, которых нету в linux. Т.е. с виду работоспособный код для Windows под linux просто выдаст ошибку отсутствия функций. Действительно, разная реализация сокетов в Windows и Linux имеет место. Но, что касаемо MSYS2, то лучше сперва прокачать вопрос, а потом утверждать. Дело в том, что перечисленные мною выше тулчейны не смогут собрать код для Linux-сокетов, просто не найдут Linux-специфических заголовков. Но все же MSYS2 - эмулятор Linux и у него кроме mingw-w64-* есть еще свой тулчейн /msys. Приведу пример, топикстартеру, уверен, пригодится ... Сперва установим необходимое ![]() ![]() pacman -S msys/gcc pacman -S msys/gcc-libs pacman -S msys/binutils pacman -S msys/cmake pacman -S msys/ninja Да, при установке некоторые пакеты могут быть поставлены как зависимости к ранее поставленным пакетам, в этом случае можно повторно не ставить. К примеру установка /msys/gcc может подтянуть сразу /msys/gcc-libs и /msys/binutils. Я уже не помню, но что-то такое было. Не суть. Тестируем "родной" тулчейн По уже знакомому сценарию делаем проект, пусть в каталоге ~/dev/projects/echo-test, туда кладем файлы: server.cpp ![]() ![]() #include <iostream> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> int main() { int server_fd, new_socket, valread; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; const char *hello = "Hello from server"; if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } valread = read(new_socket, buffer, 1024); printf("%s\n", buffer); send(new_socket, hello, strlen(hello), 0); printf("Hello message sent\n"); return 0; } client.cpp ![]() ![]() #include <iostream> #include <cstring> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> int main() { int sock = 0, valread; struct sockaddr_in serv_addr; const char *hello = "Hello from client"; char buffer[1024] = {0}; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { std::cerr << "\n Socket creation error \n"; return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(8080); if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { std::cerr << "\nInvalid address/ Address not supported \n"; return -1; } if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { std::cerr << "\nConnection Failed \n"; return -1; } send(sock, hello, strlen(hello), 0); std::cout << "Hello message sent\n"; valread = read(sock, buffer, 1024); std::cout << buffer << std::endl; return 0; } CMakeLists.txt ![]() ![]() cmake_minimum_required(VERSION 3.0) project(TestThreads) set(CMAKE_CXX_STANDARD 11) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") add_executable(server server.cpp) add_executable(client client.cpp) build.sh ![]() ![]() #!/usr/bin/sh mkdir build cd build cmake -G Ninja .. ninja Запускаем сборку. Следует заметить, что в пакетном файле переменную окружения PATH мы не модифицируем. Тем самым запускается "родная" версия cmake, которая также ищет "родные" компиляторы и бинутилсы, которые располагаются непосредственно в /usr/bin. После сборки получаем два исполняемых файла формата PE (виндовых). Однако, хоть и проект был собран статически, одна динамическая зависимость осталась. Для работы исполняемым файлам нужно положить рядом msys-2.0.dll (его можно взять из /usr/bin). Запускаем сперва server.exe - программа висит и ждёт. Запускаем во втором окне client.exe. Обе программы завершают свою работу. При этом в окне sever.exe видим вывод: ![]() ![]() Hello from client Hello message sent А в окне client.exe: ![]() ![]() Hello message sent Hello from server Вот, собственно, такими нехитрыми манипуляциями мы собрали Linux-специфичный проект, и запустили его под M$ Windows ![]() |
Сообщ.
#47
,
|
|
|
Цитата Majestio @ Но все же MSYS2 - эмулятор Linux и у него кроме mingw-w64-* есть еще свой тулчейн /msys. Thanks за пример, даже не верится, что под винду заработает без WSAxxxx. В целом, то же самое, что я уже делал неоднократно, вот например из последнего: https://github.com/MrDemonid/Sync-time-from-NTP Но тогда уж вопрос на засыпку. У меня все попытки установить MSYS2 провалились, скорее всего из-за ошибок установки. И сейчас у меня просто minGW, в которой нет даже намёка на MSYS, то есть тупо вообще нет соответствующей консоли, так что ничего доставить не могу. И как быть? Ставить заново MSYS2? Так то я не против попробовать снова, но что делать с текущим minGW? Сейчас прошелся поиском и не нашел в папке minGW ключевых инклюдов: inet.h и socket.h так что по любому что-то делать нужно. А я то наивно думал, что самое сложное позади ![]() |
Сообщ.
#48
,
|
|
|
MSYS2 вроде заработал, всего одна ошибка при установке. Проект компилируется, правда только из терминала, VSCode поломался и ни в какую не создаёт нормальные json файлы. Подружить бы его с makefile для cmake, но пока итак пойдёт.
Осталось только доделать. Всем спасибо за помощь и советы! |
Сообщ.
#49
,
|
|
|
Цитата Eretic @ Так то я не против попробовать снова, но что делать с текущим minGW? Это вопрос тем, кто посоветовал ![]() |
Сообщ.
#50
,
|
|
|
Цитата Eretic @ Сейчас прошелся поиском и не нашел в папке minGW ключевых инклюдов: inet.h и socket.h А нет ли там файлов "windows.h", "winsock.h", "winsock2.h", "wininet.h" ? Вариант поиска: Во всех файлах *.h ищем ключевое слово "socket". Добавлено Цитата Eretic @ так что по любому что-то делать нужно. А я то наивно думал, что самое сложное позади ![]() Сложности только начинаются. Поскольку кроме поставленной задачи, ты начал решать ещё одну задачу - "кросплатформенность". Ещё не известно, что сложнее. Наверняка будет много сюрпризов. Обычный из них - всё было хорошо и правильно для Виндуса. При попытке собрать приложение плд Линуксом исходники просто не компилируются. |
Сообщ.
#51
,
|
|
|
Цитата ЫукпШ @ А нет ли там файлов "windows.h", "winsock.h", "winsock2.h", "wininet.h" ? Есть. Но это вариант виндозный и немного не то. Хотя на нём конечно получилось бы намного красивее и проще, чем сейчас замучиваю с select() ![]() Цитата ЫукпШ @ Поскольку кроме поставленной задачи, ты начал решать ещё одну задачу - "кросплатформенность". Ещё не известно, что сложнее. Меня больше пугают установки неизвестных доселе пакетов, структуры которых я не понимаю. Теперь вот более-менее разобрался. О кроссплатформенности мне пока рано думать. Я же в качестве студента на каникулы заявку подал. Вряд ли кто-то ожидает, что бестолковый студент сразу начнет решать сложнейшие задачи, вызывающие головную боль даже у профессионалов ![]() А программки заработали. Единственный косяк - это забыл что в первый параметр select() нужно передавать значение на 1 больше сокета (максимального из набора) и почти час не мог понять - отчего постоянно выходит только по таймауту. Да, функция допотопная, но зато совместимость 100% и задаче отвечает полностью (приложения не должны зависеть друг от друга, а продолжать спокойно работу в случае закрытия одного их них) ![]() Добавлено Цитата ЫукпШ @ При попытке собрать приложение плд Линуксом исходники просто не компилируются. Но ведь я компилирую gcc? То есть тем самым компилятором, что является основным в линуксе. Что тут может пойти не так? |
Сообщ.
#52
,
|
|
|
Цитата Eretic @ Но ведь я компилирую gcc? То есть тем самым компилятором, что является основным в линуксе. Что тут может пойти не так? Все просто. Нужно просто прочесть расшифровку MinGW - Minimalist GNU for Windows. Там нет и не может быть заголовочных файлов для Linux, т.к. это инструмент заточен именно для Windows. |
Сообщ.
#53
,
|
|
|
Цитата Majestio @ ужно просто прочесть расшифровку MinGW - Minimalist GNU for Windows. Так я сейчас перешел с minGW на MSYS2. К тому же из инклюдов у меня только: #include <iostream> #include <thread> #include <algorithm> #include <list> #include <condition_variable> #include <mutex> #include <chrono> #include <sys/socket.h> #include <sys/select.h> #include <arpa/inet.h> #include <unistd.h> Вроде ничего специфического, чисто плюсовые примочки, которые должны быть реализованы под любую платформу. Разве нет? |
Сообщ.
#54
,
|
|
|
Цитата Eretic @ которые должны быть реализованы под любую платформу. Разве нет? Чтобы код был кроссплатформенным, нужно примерно следующее: ![]() ![]() #ifdef _WIN32 // Заголовки для Windows с использованием MinGW-w64 #include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") #else // Заголовки для Linux #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> #endif Тулчейн /mingw32 будет использовать первую часть (виндовую), а /msys будет использовать вторую часть (линуховую). Соответственно, и в дальнейшей реализации нужно писать отдельные части для виндовс и линух, помещая их в блоки #ifdef. В стандарте С++ нет унифицированной работы с TCP/IP, поэтому указанные выше заголовки - платформозависимые. |
Сообщ.
#55
,
|
|
|
Цитата Majestio @ #ifdef _WIN32 // Заголовки для Windows с использованием MinGW-w64 #include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") А зачем мне winsock, если у меня и без него всё работает? Говорю же, у меня подключено как раз вот это: Цитата Majestio @ #else // Заголовки для Linux #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> #endif И прекрасно работает под виндой. Еще разберусь, почему клиент не опознаёт потерю связи и можно сдать задание. С другой стороны, не распознает и фиг с ней, всё равно данные будут потеряны (в задаче нет ни слова о их хранении до восстановления связи). Но в принципе можно проверить. Если есть желающий попробовать компильнуть под линуксом и проверить в работе, то пишите. Как только закончу - вышлю ![]() |
Сообщ.
#56
,
|
|
|
Цитата Eretic @ А зачем мне winsock, если у меня и без него всё работает? Говорю же, у меня подключено как раз вот это: А потому, что дальше у тебя возникнет желание использовать WinAPI, а с "линуксовым" тулчейном тебя поприветствует облом. Нет в нем поддержки Windows, только ограниченная эмуляция (трансляция) линуховых вызовов в виндовые. |
Сообщ.
#57
,
|
|
|
Ну как, найдётся желающий протестировать под линуксом?
|
Сообщ.
#58
,
|
|
|
Всем привет!
Мне естественно отказали, но я и не больно то надеялся, всё-таки первый раз в жизни что-то на ООП делал ![]() Сейчас уже завершаем знакомство с линуксом (убунтой), так что ради интереса скомпилировал и под линукс - прекрасно работает, без каких-либо изменений в исходниках. Даже не верится, что смог создать сорсы под две совершенно разные системы. И непонятно что им там не понравилось? Возможно мой ООП-подход, в стиле Java ![]() ![]() Ну да ладно. Сейчас готовлю проект для диплома. GUI уже создана на Java Swing, всё работает, данные принимает и выдает ответы обратно, в Controller, который пересылает их в Model (естественно реализовал модель MVC). Теперь пару вопросов осталось решить: 1) Клиент - это кто шлет запрос, а сервер - кто отвечает на них. Но у меня такая ситуация, что запросы возможны с любой стороны, как и ответы. Так кого лучше сделать клиентом, а кого сервером - GUI на Java или DLL на Си (она как раз отвечает за обмен данными с оборудованием по RS232, точнее будет отвечать, когда реализую)? 2) Хочу использовать GCC, чтобы основная часть DLL нормально компилировалась как под винду, так и под линукс (кроме api-зависимой части работы непосредственно с RS232). Объясните мне уже, чем отличаются все эти /clang от /usr и /ucrt? Просто MSYS2 по дефолту создал в винде все папки, а что мне нужно то? В чем отличия всех этих компиляторов? Нафига такое многообразие? Извиняюсь, если уже где-то говорили об этом, мог и пропустить - времени вообще ни на что не хватает ![]() PS: просто прошло столько времени, что я уже и не помню чем компилировал под винду - комп то уже новый. |
Сообщ.
#59
,
|
|
|
Цитата Eretic @ 1) Клиент - это кто шлет запрос, а сервер - кто отвечает на них. Но у меня такая ситуация, что запросы возможны с любой стороны, как и ответы. Обмен между "клиентом" и "сервером" в большинстве случаев - двусторонний. Разница только в том - кто "задает работу" (клиент) и кто "её работает" (сервер). Цитата Eretic @ Так кого лучше сделать клиентом, а кого сервером - GUI на Java или DLL на Си (она как раз отвечает за обмен данными с оборудованием по RS232, точнее будет отвечать, когда реализую)? Ну тут как бы очевидно - Java напрямую с железом работать не может. Вернее может - но через подключаемые либы, которые реализуются "не на Javа". Соответственно клиента пишешь на Java, а на С/C++ сервер, который будет обрабатывать запросы и взаимодействовать с RS232. Цитата Eretic @ 2) Хочу использовать GCC, чтобы основная часть DLL нормально компилировалась как под винду, так и под линукс (кроме api-зависимой части работы непосредственно с RS232). Объясните мне уже, чем отличаются все эти /clang от /usr и /ucrt? Просто MSYS2 по дефолту создал в винде все папки, а что мне нужно то? В чем отличия всех этих компиляторов? Нафига такое многообразие? Извиняюсь, если уже где-то говорили об этом, мог и пропустить - времени вообще ни на что не хватает clang32/64 отличается от mingw32/64 только тем, что является для mingw32/64 фронтендом, вернее для тамошнего gcc. А вообще Clang является фронтэндом для компиляции множества языков программирования: C, C++, Objective-C и Objective-C++. Он работает вместе с компилятором LLVM и является частью проекта LLVM. Его использовать предпочтительнее gcc по причине лучшей скорости и более детальному анализу кода. В системах Windows/Linux clang и его binutils использует все от gcc. А вот в в в системах семейства *BSD/macOSX для clang своя реализация стандартной библиотеки С++ (которая обгоняет реализацию стандарта по сравнению с GCC, но и где-то уступает). Но это для тебя несущественно. Просто используй clang 32 или 64, в зависимости от нужной тебе разрядности. А вот с UCRT другой вопрос. Если тебе не волнуют системы ниже Windows 8.0 - используй UCRT. Говорят, это более легковесная реализация CRT, но не работает на более ранних версиях Винды. Хотя зачем рисковать перед дипломом - может комиссия из олдфагов, которые признают только Windows 7? А еще лучше прокачай этот вопрос сам - тебя же не банили в Гугле? ![]() |
Сообщ.
#60
,
|
|
|
Ясно. В гугле конечно не забанили, но толковой инфы что-то не находил, чтобы коротко и ясно. Полно описаний установки MSYS2, но в них подразумевается, что человек уже знает что к чему и зачем.
|