Хотел на Ачате выложить , а он седня с*** не пашет , ну для поддержания проэкта >
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 даёт нам вод такой пример :
Переведя 'наскоком' на C# мы получим вот такой код :
Но этот код будет несовсем точным т к C# очен требователен в отношении типов данных
(см про явные и неявные преобразования в C#)
В итоге , уточнив типы данных, приходим вот такому , наиболее точному коду :
Собственно вот они элементарные трудности перевода ...
Теперь , имея свой WSA_Data импортируем саму функуцию:
при этом обьявим константу для версии сокета...
public const short WORD_VERSION = 36;
Функцию мы подготовили ...
Используем вот так:
Соответственно нам понадобится узнавать ошибки:
WSAGetLastError обьявдяется так же как и в C++ ...
Новичкам следует заметить , что для вывода результата , например в MessageBox ,нужно преобразовать его в строку (прим. в текст)...
Далее перейдем к функции socket();
msdn описание:
SOCKET WSAAPI socket(
__in int af,
__in int type,
__in int protocol
);
В случае успеха функция возвращает дискриптор нового сокета ... в С++ тип int почти универсален для функций ,в C# для дескриптора мы будем использовать специальный тип IntPtr.
IntPtr – это platform-specific тип, который используется для представления указателей или дескрипторов...
константы:
Конструкция:
Теперь переидем к функции bind. Функция bind ассациирет (привязывает) сокет к локальному адресу.
Обьявим структуру sockaddr
Новичкам следует обратить внимание на модификатр ref . Этот модификатор одновременно является и in и out модификатором. Дело в том, что при использовании параметра с модификатором ref объект передается в метод по ссылке. В результате метод получает возможность изменить этот объект. Очень часть таким способом передаются массивы." (blog.excode.ru)
для заполнения структуры нам понадобятся еще функции htons(преобразовывающая данные для их правильности при использовании WinSock) и inet_addr(для преобразования строки с IP-адресом в формате десятичное с точкой в 32-разрядное двоичное число (с сетевым порядком байтов)).
Теперь же создадим и заполним эту структуру , в итоге обьединим в небольшую функцию:
Теперь уже , более мение разобравшись наиболее трудными (для новичка) с типами и структурами данного примера мы уже без труда можем оперировать с основными функциями WinSock ...
<не буду повторяться продолжая писать уже однообразный код к каждой йункции , хотя при освоении языка мне этот процесс показался довольно интересным и увлекательным>
Дальше вам поможет Msdn , Гугл и собственное стремление ...
[bonus]
небольшая подсказка:
[outro]
Я хотел описать все функции и впринципе можно было добавить их подробное описание , но посмотрев , скока я написал вначале , я решил остановиться на основных функциях...возможно , когда будет время и желание...
Еще можно задуматься об актуальности данной статьи . Помог изобрести велосипед , можете сказать ... но это тоже полезно ...
[bonus]
Полезные ссылки по C#
http://www.intuit.ru/department/pl/csharp/
http://www.gotdotnet.ru/LearnDotNet/CSharp/default.aspx
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 даёт нам вод такой пример :
Код:
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# мы получим вот такой код :
Код:
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#)
В итоге , уточнив типы данных, приходим вот такому , наиболее точному коду :
Код:
[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 импортируем саму функуцию:
Код:
[DllImport("ws2_32.dll")]
static extern Int32 WSAStartup(Int16 wVR, WSA_Data lpWSAD);
при этом обьявим константу для версии сокета...
public const short WORD_VERSION = 36;
Функцию мы подготовили ...
Используем вот так:
Код:
WSA_Data wsaData = new WSA_Data();
if (WSAStartup(WORD_VERSION, wsaData) != 0)
{
MessageBox.Show("WSAStartup error");
}
Соответственно нам понадобится узнавать ошибки:
WSAGetLastError обьявдяется так же как и в C++ ...
Код:
[DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern Int32 WSAGetLastError();
Новичкам следует заметить , что для вывода результата , например в MessageBox ,нужно преобразовать его в строку (прим. в текст)...
Код:
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 тип, который используется для представления указателей или дескрипторов...
Код:
[DllImport("wsock32.dll")]
static extern IntPtr socket(long af, long s_type, long protocol);
константы:
Код:
public const int AF_INET = 2;
public const int SOCK_STREAM = 1;
public const int PPROTO_TCP =6
public const int PPROTO_UDP = 17
Конструкция:
Код:
IntPtr s = socket(AF_INET, SOCK_STREAM, PPROTO_TCP);
if (s.ToInt32() != 0)
{
MessageBox.Show("Socket Error:" + WSAGetLastError().ToString());
}
Обьявим структуру sockaddr
Код:
public struct sockaddr
{
public short sin_family;
public short sin_port;
public int sin_addr;
public long sin_zero;
}
Код:
[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-разрядное двоичное число (с сетевым порядком байтов)).
Код:
[DllImport("ws2_32.dll")]
static extern short htons(int hostshort);
[DllImport("wsock32.dll")]
static extern int inet_addr(string cp);
Теперь же создадим и заполним эту структуру , в итоге обьединим в небольшую функцию:
Код:
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;
}
<не буду повторяться продолжая писать уже однообразный код к каждой йункции , хотя при освоении языка мне этот процесс показался довольно интересным и увлекательным>
Дальше вам поможет Msdn , Гугл и собственное стремление ...
[bonus]
небольшая подсказка:
Код:
[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#
http://www.intuit.ru/department/pl/csharp/
http://www.gotdotnet.ru/LearnDotNet/CSharp/default.aspx