Портативность Winsock 2
-
06-07-2019 - |
Вопрос
Я собираюсь разработать некоторые вещи, связанные с сокетами, на C++ и хотел бы, чтобы программное обеспечение было как можно более переносимым между Windows и Linux с самого начала (сделать его переносимым позже сложно).
Я просмотрел разные библиотеки, есть одна для C++ от alhem.net и, конечно, есть boost::asio.boost::asio выглядит очень многообещающе, но для таких маленьких приложений это будет очень большая зависимость.
Стоит ли вообще писать это самому или мне просто использовать библиотеку?Если я сделаю это сам, какие будут основные подводные камни?
Решение
Winsocks не очень совместимы с сокетами Posix:
- В Winsocks сокет имеет тип
SOCKET
.В Posix это просто дескриптор файла (int
), на котором вы можете выполнять обычныеread()
иwrite()
звонки. - Они не возвращают ошибки одинаково.
- Они не поддерживают некоторые параметры
recv()
иsend()
. - Вам необходимо инициализировать и унифицировать библиотеку Winsocks с помощью двух специальных функций.
- Я не думаю, что вы можете закрыть сокеты Windows с помощью
shutdown()
илиclose()
.Это что-то вродеclosesocket()
вместо.
Должно быть больше различий, но это то, что я могу вспомнить прямо сейчас.Если вам нужна переносимость с помощью Winsocks, у вас будет небольшая библиотека для закрытия сокета, печати сообщения об ошибке и т. д.
Я бы, наверное, пошел с boost::asio
, лично (правда, я никогда им не пользовался).
Другие советы
Я разработал несколько портативных оберток для сокетов.Убедитесь, что вы не идете по дрянной полосе невозврата, состоящей из событий WinSock2.Помимо этого, насколько я понимаю, самые большие различия заключаются в следующем:
- чтобы начать работу в сети в Windows, вам нужно позвонить
::WSAStartup()
, чтобы выключить его в Windows, запустите::WSACleanup()
;в Linux ничего не делать, close()
в Linux естьclosesocket()
в Windows,- Размеры буфера по умолчанию различаются как в драйверах, так и в операционных системах, поэтому обязательно установите их с помощью
SO_RCVBUF
иSO_SNDBUF
, - SO_REUSEADDR крадет адрес в Windows, позволяет частое повторное открытие в Linux;вы, вероятно, захотите использовать этот флаг только в Linux,
- сделать сокет неблокирующим использованием
::ioctlsocket()
в Windows,::fcntl()
в Linux, - файлы заголовков разные,
<sys/socket.h>
и друзья в Linux,<WinSock.h>
в Windows, - чтобы стать портативным, самый простой способ, вероятно, использовать
::select()
дождаться поступления данных, fd_set
в Windows/Linux они совершенно разные;это актуально только в том случае, если вам нужно оптимизировать инициализациюfd_set
s, например, при добавлении/удалении произвольных сокетов,- в Windows любой поток, зависший в сокете, выдается с кодом ошибки при закрытии сокета, в Linux поток остается в ожидании.Если поток блокирует сокет, например,
::recvfrom()
, вы можете рассмотреть возможность использования::sendto()
чтобы освободить поток зависания под Linux.
Все остальное, что мне когда-либо было нужно, просто получилось из лоды.
Посмотрите на " Adaptive Communications Environment " (ACE) библиотека: (домашняя страница ACE) Он предоставляет несколько хороших абстракций и большую гибкость в виде переносимой библиотеки, которая поддерживает Windows, MacOS и Linux. У этого есть немного крутая кривая изучения, но я получил очень хорошее значение от этого.
Сколько штук сокетов вы будете использовать? Я сделал несколько приложений, где сокеты были довольно высокого уровня (открывать, читать, писать) и отлично работали от Windows до Linux. Если это больше, чем это - иди с наддува.
Честно говоря, я бы использовал boost :: asio в качестве первого предпочтения. Если вы действительно хотите разобраться с API сокетов, вы можете использовать стандартный API сокетов в стиле BSD как для Windows, так и для Linux - просто в Windows вам нужно будет ссылаться (и инициализировать) на Winsock2, тогда как на В Linux у вас не будет отдельной библиотеки для ссылок.
Посмотрите на это ... http://sourceforge.net/projects/cpp- розетки / р>