[ WinSockets _C# или велосипед голыми руками ] [интро] Собственно в этой статье нет ничего нового , особенного ... Я даже не могу толком сказать , для кого эта статья ориентирована ... в первую очередь для новичков в C# ... Предворительно , читатель уже разбирается в win сокетах , например знает C++ , в C# недавно... Вот , представим читающий знает C++ и изучая C# хочет работать с советыми максимально 'близко'... Но думаю начинающему изучать c# будет полезно ... [абоут] В статье мы будем использовать Winsock , не подключая System.net.sockets , а напрямую из ws2_32.dll и wsock32.dll , импортируя необходимые нам функции ... Я опишу , возможные ошибки и трудности с типами пременных, которые могут возникнуть... [go] ну ладно , теперь уже приступим : Как я уже говорил , мы будем импортировать функции из библиотек... пожалуй приступим: (инклудим dll-импорт) using System.Runtime.InteropServices; Для начала нам понадобится WSAStartup ... Подключив System.Net.Sockets мы вообще можем не думать о инициализации ... имея заголоваочный файл winsock2.h , в C++ эта функция задается вот так: WSADATA wdata; WSAStartup(MAKEWORD(2,2), &wdata); Здесь нам прилется самим обьявить и заполнить struct wsadata: MSDN даёт нам вод такой пример : Code: typedef struct WSAData { WORD wVersion; WORD wHighVersion; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR* lpVendorInfo; } WSADATA, *LPWSADATA; Переведя 'наскоком' на C# мы получим вот такой код : Code: public struct WSA_Data{ public int wVersion; public int wHighVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x101)] public string szDescription; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x81)] public string szSystemStatus; public int iMaxSockets; public int iMaxUdpDg; public long lpVendorInfo; Но этот код будет несовсем точным т к C# очен требователен в отношении типов данных (см про явные и неявные преобразования в C#) В итоге , уточнив типы данных, приходим вот такому , наиболее точному коду : Code: [StructLayout(LayoutKind.Sequential)] public class WSA_Data { public Int16 wVersion; public Int16 wHighVersion; public String szDescription; public String szSystemStatus; public Int16 iMaxSockets; public Int16 iMaxUdpDg; public IntPtr lpVendorInfo; } Собственно вот они элементарные трудности перевода ... Теперь , имея свой WSA_Data импортируем саму функуцию: Code: [DllImport("ws2_32.dll")] static extern Int32 WSAStartup(Int16 wVR, WSA_Data lpWSAD); при этом обьявим константу для версии сокета... public const short WORD_VERSION = 36; Функцию мы подготовили ... Используем вот так: Code: WSA_Data wsaData = new WSA_Data(); if (WSAStartup(WORD_VERSION, wsaData) != 0) { MessageBox.Show("WSAStartup error"); } Соответственно нам понадобится узнавать ошибки: WSAGetLastError обьявдяется так же как и в C++ ... Code: [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern Int32 WSAGetLastError(); Новичкам следует заметить , что для вывода результата , например в MessageBox ,нужно преобразовать его в строку (прим. в текст)... Code: if (WSAStartup(WORD_VERSION, wsaData) != 0) { MessageBox.Show(WSAGetLastError().ToString()); } Далее перейдем к функции socket(); msdn описание: SOCKET WSAAPI socket( __in int af, __in int type, __in int protocol ); В случае успеха функция возвращает дискриптор нового сокета ... в С++ тип int почти универсален для функций ,в C# для дескриптора мы будем использовать специальный тип IntPtr. IntPtr – это platform-specific тип, который используется для представления указателей или дескрипторов... Code: [DllImport("wsock32.dll")] static extern IntPtr socket(long af, long s_type, long protocol); константы: Code: public const int AF_INET = 2; public const int SOCK_STREAM = 1; public const int PPROTO_TCP =6 public const int PPROTO_UDP = 17 Конструкция: Code: IntPtr s = socket(AF_INET, SOCK_STREAM, PPROTO_TCP); if (s.ToInt32() != 0) { MessageBox.Show("Socket Error:" + WSAGetLastError().ToString()); } Теперь переидем к функции bind. Функция bind ассациирет (привязывает) сокет к локальному адресу. Обьявим структуру sockaddr Code: public struct sockaddr { public short sin_family; public short sin_port; public int sin_addr; public long sin_zero; } Code: [DllImport("wsock32.dll")] public static extern int bind(IntPtr socket, ref sockaddr addr, int namelen); Новичкам следует обратить внимание на модификатр ref . "Этот модификатор одновременно является и in и out модификатором. Дело в том, что при использовании параметра с модификатором ref объект передается в метод по ссылке. В результате метод получает возможность изменить этот объект. Очень часть таким способом передаются массивы." (blog.excode.ru) для заполнения структуры нам понадобятся еще функции htons(преобразовывающая данные для их правильности при использовании WinSock) и inet_addr(для преобразования строки с IP-адресом в формате десятичное с точкой в 32-разрядное двоичное число (с сетевым порядком байтов)). Code: [DllImport("ws2_32.dll")] static extern short htons(int hostshort); [DllImport("wsock32.dll")] static extern int inet_addr(string cp); Теперь же создадим и заполним эту структуру , в итоге (обобщив) получим небольшую функцию: Code: public static bool AdvBind(string ipAddress, int port,IntPtr socketHandle) { sockaddr remoteAddress; // Обьявляем int resultCode = 0; //это будет код резудбтата int errorCode = 0; //а это код (в сучае) ошибки bool returnValue = false; // то - что будет возвращать функция if (socketHandle != IntPtr.Zero) // проверяем валидность сокета { try { remoteAddress = new sockaddr(); remoteAddress.sin_family = AF_INET; remoteAddress.sin_port = htons((short)port); remoteAddress.sin_addr = inet_addr(ipAddress); remoteAddress.sin_zero = 0; if (remoteAddress.sin_addr != 0) { resultCode = bind(socketHandle,ref remoteAddress,Marshal.SizeOf(remoteAddress)); errorCode = WSAGetLastError(); returnValue = (resultCode == 0); } } catch { returnValue = false; } } return returnValue; } Теперь уже , более мение разобравшись наиболее трудными (для новичка) с типами и структурами данного примера мы уже без труда можем оперировать с основными функциями WinSock ... <не буду повторяться продолжая писать уже однообразный код к каждой йункции , хотя при освоении языка мне этот процесс показался довольно интересным и увлекательным> Дальше вам поможет Msdn , Гугл и собственное стремление ... [bonus] небольшая подсказка: Code: [DllImport("wsock32.dll")] static extern int connect(IntPtr socket,sockaddr addr, int addrlen); [DllImport("wsock32.dll")] static extern int recv(IntPtr socket, string buf, int len, int flag); [DllImport("wsock32.dll")] static extern long WSAAsyncSelect(IntPtr socket, long hwnd, long iMsg, long lEvent); [DllImport("ws2_32.dll", CharSet=CharSet.Auto, SetLastError=true)] static extern IntPtr accept( IntPtr socketHandle, ref sockaddr socketAddress, ref int addressLength); [DllImport("wsock32.dll")] static extern int closesocket(IntPtr s); [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern Int32 WSACleanup(); [outro] Я хотел описать все функции и впринципе можно было добавить их подробное описание , но посмотрев , скока я написал вначале , я решил остановиться на основных функциях...возможно , когда будет время и желание... Еще можно задуматься об актуальности данной статьи . Помог изобрести велосипед , можете сказать ... но это тоже полезно ... [bonus] Полезные ссылки по C# Code: http://www.intuit.ru/department/pl/csharp/ http://www.gotdotnet.ru/LearnDotNet/CSharp/default.aspx
ты че это нехакерский способ. вот, скажем, придумать способ писать asm-вставки в .net - это для античатовцев настоящих.