Comments 50
«Что меня всегда раздражало в библиотеке WS2 — так это способы возвращения ошибок, и чтения информации.»

Если вы не знали, хотел бы заметить, что такой способ обработки ошибок — это специфика WinAPI. В нем все (или большинство) функции возвращают коды ошибок, в том числе через HRESULT, 0, -1… Ну а GetLastError — это вовсе как раз системная функция созданная для того, чтобы понять что собственно произошло.

Собственно, переход на обработку ошибок через исключения — это одно из ключевых особенностей платформы .net. В момент выхода этот момент широко рекламировался, позиционировался как решение проблемы разнообразия и бардака с кодами ошибок.

* если вы это знали, то, надеюсь, информация пригодится тем, кто не знал
Хм, ну, это да, я это знаю и испытал на собственном горбу не раз 8-)
Не против, если я добавлю эту информацию в статью? 8-)
UFO landed and left these words here
согласный, но ключевое слово здесь «исключительные» ситуации, когда они случаются, то скорость уже отходит на несколько другой план

тут, как и везде, и лекарство и яд — все зависит от дозы и того как программист использует механизм
Действительно, если заниматься тем, что оборачивать всю программу в try catch — это уже не серьёзно. Ещё более несерьёзно — передавать сообщения исключениями (Такое тоже было, некоторые люди так выходили из десятков вложенных циклов.)

А если у нас по исключению рухнул удалённый сервер — можно уже не торопиться. Сервер лежит, скорость не важна 8-)
«Исключения — штука весьма медлительная» — при возникновении с вероятностью 1/100000 это не серьезно, а если у вас исключения 1/2 то значит что код кривой ))) хардом орехи не колим

«В итоге, работа с сокетами превратилась в песню» — буду критичен, как SDM заявляю что код отвратительный.

1. Цикломатичен
2. Смысла в try/catch никакого
3. Дублирование
4. Неверный

Замечания по статье:
.NET Socket в конечном итоге также вызывает функции winsock, с чего вы решили что ваша реализация лучше?
Для pinvoke в .NET есть замечательная функция — Marshal.GetLastWin32Error(), при получении нативной ошибки в pinvoke брать результат нужно именно ей, а не обёрткой над нативной GetLastError() :-)

* это так, если кто не знал
Если дергаете функции WinSock то желательно получать ошибку с помощью обертки над WSAGetLastError(), проверено на опыте.
В атрибуте DllImport есть параметр SetLastError. Пример из MSDN:

[DllImport(«user32.dll», SetLastError=true)]
public static extern int MessageBoxA(int hWnd, String text, String caption, uint type);

После вызова функции маршаллер вызовет winapi-функцию GetLastError и сохранит возвращённое значение. Потом его можно будет получить через Marshal.GetLastWin32Error.

MSDN говорит, что значение по умолчанию — false. Возможно, если оно false, то GetLastWin32Error будет не возвращать сохранённое значение, а вызывать GetLastError непосредственно.
> Ну, можно попытаться ускорить ваше приложение, используя вычисления на очень сложном и быстром Assembler'е.

Только предварительно прикинуть, покроет ли «сложный и быстрый ассемблер» затраты на P/Invoke и не создаст ли это дофига дополнительных проблем с разрядностью native-кода.
Как показала практика WPF, который для рендеринга контролов использует нативные методы работы с DirectX — всё не так плохо.
С чего вы взяли, что он использует для этого p/invoke? Для этого есть более подходящие методы.
Например вот здесь можно почитать о библиотечке milcore.dll, которая работает на анменеджеде и является самым базовым компонентом WPF
Спасибо, мне это известно.
Вопрос был о том, с чего вы решили, что для вызова анменеджеда используется p/invoke?
Пинвок — это технология межпрограммного взаимодействия. Через что именно она работает в милкоре — это ещё надо поискать 8-). Факт в том, что она там есть, хотя не факт, что на Дллиморте.
ПИнвок предполагает маршаллинг типов в процессе вызова, что в общем и приводит к потере производительности.
А вот при вызове managed -> unmanaged (или наоборот) из, скажем, C++/CLI, маршаллинг не применяется, а просто соблюдается соответствующая конвенция вызова.
В лучших традициях велосипедостроения :))

В .net платформе реализован доступ практически ко всем ф-циям, в очень удобном виде. Для сокетов в свою очередь есть socket

Показать пример Interop людям, это конечно хорошо, но следовало бы показать там, где это действительно нужно, в 99% случаев в этом нет необходимости.

Я об этом упоминал всю статью 8-) Это — пример, который показывает, как реализовывать. Другое дело, что сокеты — это всегда интересно и прикольно.
Согласен по-поводу 99%. Мне редко вообще приходилось этим пользоваться. Например, необходимо было в OpenFileDalog отображать эскизы страниц, что оказалось не реализуемо средствами.нет, вот пришлось использовать Interop.

[DllImport(«user32.dll», EntryPoint=«SendMessageA», CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
private static extern uint SendMessage(uint Hdc, uint Msg_Const, uint wParam, uint lParam);
[DllImport(«user32.dll», EntryPoint=«FindWindowExA», CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
private static extern uint FindWindowEx(uint hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow); [DllImport(«user32.dll»,EntryPoint=«GetForegroundWindow»,CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)] private static extern uint GetForegroundWindow();

private void ThumbNailActiveWindow()
{
lock(this)
{
uint listviewHandle = 0;
while(listviewHandle == 0 && isWatching)
{
listviewHandle = FindWindowEx(GetForegroundWindow(), 0, «SHELLDLL_DefView», "");
}
if(listviewHandle != 0)
{
SendMessage(listviewHandle, WM_COMMAND, 0x702d, 0);
}
}
}
В смысле? Вы про конечный проект? Мы просто сделали просто. Мы добавили в списки все чарсэты, поддерживаемые конечной системой.
Я про P/Invoke объявления.
Зачем, например, указывать CharSet.Auto на функциях, которые и со строками-то не оперируют вовсе? :)
Мы были молоды 8-)

Основные проблемы были с тем, как наш сервер взаимодействует с серверами, не понимающими UTF-8. После долгих сношений родили вот это.
UFO landed and left these words here
А как побеждали тормоза с постоянным переключением managed/unmanaged? unsafe?
тут проблема в основном из-за маршалинга параметров и результата. к примеру строк или байтовых массивов, т.к. данные обычно копируются в/из манадж памяти. если дергаете void Method() то особых тормозов не будет :)
Скажем так, на текущих объёмах у нас вообще не было тормозов. Они не могли появиться при таком раскладе.
итог какой статьи? на сколько быстро ипользовать winapi через этот кошмар чем использовать существующие обертки в .net?
Статьи итог такой: не под всё есть обёртки, иногда надо кошмарить.
ну тогда пример плохой, так как это можно сделать уже существующими обертками.
Было супер имено посмотреть сравнение насколько быстро был написан код на том или на том. и на сколько быстро работает то или иное. а так статья получается просто про то как вызвать с/c++ библиотеку из .net
Эм, посмотрите там, в тексте статьи все обоснования того, почему эта статья такая.
btw, недавно писал про альтернативный метод интеропа с .NET через C++/CLI — habrahabr.ru/blogs/programming/47732/

здорово помогает, когда надо C++-код обернуть

а иногда просто лень с настройкой маршаллинга в P/Invoke возиться, делаю тонкую обертку с .NET-интерфейсом прямо на C++/CLI
А вы молодец, хорошую статью написали. Сам помню так же велосипедили года 2 назад, когда у нас сети были :).
Только я потом узнал, что .Net sockets очень медленные, особенно когда они используются асинхронно. Посему если критична скорость, то лучше написать свою обёртку, только писать её нужно эээ… немножко… подругому ;).
Хехехе, изначально мы в инсте хотели сдать WCF вместо сокетов
Машинный код .NET и машинный код Native (Не-.NET) приложений это не одно и то же. Соответственно, выходит интересная штука: мы можем взять одно Native приложение, написанное на языке Assembler, и взять другое Native приложение, написанное я языке Pascal, и скрестить их вместе.

Как-то я не понял логический переход:) Можно пояснить?
Два предложения. Каждое логически обособленно. Такое бывает с предложениями. 8-)
Вот именно, что не обособленно:) У вас из первого выходит второе. Я сидел некоторое время втыкал, почему из того, что машинные коды не одно и то же следует связка ассемблера с паскалем :D
Что занчит машинный код .Net? IL? Так это не машинный код. Машинным он становится только после jit-компиляции.

Мы долго искали компромиссы с нашим преподом, и в итоге пришли к следующему: Нам позволяют использовать .NET при условии, что WS2 мы будем дёргать через DllImport.
Препод идиот, хотя в этом ничего удивительного. Как по его мнению System.Net.Sockets.Socket работает?
Эх были времена… Помню как мы уламывали препода на лабах, чтоб писать на С++, а не на фортране.

Очень интересная мысль про скрещивание с# и с. Вот предположим, есть железка — трекер, она программируется на с. Интересно, возможно ли написать управляющий код на c#, который компоновал бы инструкции С таким образом, чтобы получалась полноценная, работающая программа на с? Которую, в конечном итоге, можно было бы залить программатором в железку?
В конечном итоге — можно. Это вопрос того, что вы пишете свой компилятор на среде .NET. Фактически, вам надо находить какие-то логики кода и заменять их на последовательности байтов. Это просто делается с помощью конечных автоматов.
UFO landed and left these words here
Да куча проблем!
От банального неудобства использования до завязки на конкретную платформу.
Only those users with full accounts are able to leave comments. Log in, please.