/// <summary> /// Инициализирует экземпляр класса. /// </summary> /// <param name="appIDByte">Идентификатор приложения для FLAPHeader.ID</param> /// <param name="events">Набор событий, которые будут использованы этим экземпляром OSCARUdp</param> /// <param name="acceptsIncomingConnections"> /// Значение True указывает, что этот экземпляр OSCARUdp может принимать входящие соединения. /// В противном случае запросы на подключения из-вне будут игнорироваться. /// </param> public OSCARUdp(byte appIDByte, OSCARCallbacks events, bool acceptsIncomingConnections) : base(appIDByte, events, new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp), false) { m_needsBind = true; m_acceptsIncomingConnections = acceptsIncomingConnections; this.Connections = new List<EndPoint>(1); m_svcFlap = new FLAPHeader(appIDByte, 0, 0); }
private static void Main() { goto X5; X1: return; #region Пример сервера OSCAR // Мы можем хранит клиентов сервера в коллекцию BlockingCollection var serverClients = new BlockingCollection<OSCAR>(); // Для приема входящих соединений используем TcpListener var server = new TcpListener(IPAddress.Any, 5555); server.Start(10); // Создадим объект OSCARCallbacks, который используется классом OSCAR // каждого соединения клиента, для вызова событий. var serverOscarEventsSet = new OSCARCallbacks { Connected = (object sender, HostConnectEventArgs e) => { /* Подключение установлено только что */ }, Disconnected = (object sender, HostErrorEventArgs e) => { /* Подключение разорванно */ }, PacketReceived = (object sender, PacketEventArgs e) => { /* Принят пакет */ ((OSCAR)sender).Send(ref e.FLAP, e.Data); Console.WriteLine("[Server] <<:: " + e.FLAP); }, // .. }; // Флаг для остановки сервера bool stopFlag = false; // Для создания сервера нам понадобится примерно вот такой метод ThreadStart serverProcessor = () => { while (!stopFlag) { // У нас есть входящие подключения на очереди? if (server.Pending()) { // Принимаем входящее подключение var socket = server.AcceptSocket(); // Создадим OSCAR для работы на этом соединении var inOscar = new OSCAR(1, serverOscarEventsSet, socket, true); serverClients.Add(inOscar); } // Выполним процессинг всех подключенных клиентов foreach (var client in serverClients) client.Process(); // CPU?! TODO test Thread.Sleep(1); } Thread.CurrentThread.Abort(); }; // Запустим сервер var serverThread = new Thread(serverProcessor); serverThread.Start(); serverThread.Priority = ThreadPriority.Highest; Thread.Sleep(1000); // Для остановки сервера может быть использован примерно такой код Action stopServerExampleCode = () => { stopFlag = true; while (serverThread.IsAlive) Thread.Sleep(100); // Обязательно завершим работу сервера server.Stop(); }; //stopServerExampleCode(); #endregion X2: return; #region Пример клиента OSCAR // Создадим объект OSCARCallbacks, который используется классом OSCAR // для вызова событий var oscarClientEvents = new OSCARCallbacks { ConnectStarted = (object sender, HostEventArgs e) => { /* Начало попытки соединения */ }, ConnectFailed = (object sender, HostErrorEventArgs e) => { /* Ошибка попытки соединения */ }, Connected = (object sender, HostConnectEventArgs e) => { /* Подключение установлено */ }, Disconnected = (object sender, HostErrorEventArgs e) => { /* Подключение разорванно */ }, PacketReceived = (object sender, PacketEventArgs e) => { /* Принят пакет */ e.FLAP.Channel++; ((OSCAR)sender).Send(ref e.FLAP, e.Data); Console.WriteLine("[Client] <<:: " + e.FLAP); }, // .. }; // Создадим экземпляр класса OSCAR для работы с сетью var oscarClient = new OSCAR(1, oscarClientEvents); // Подключим его к хосту, пример var host = new NetworkHost("localhost", 5555); oscarClient.Connect(host.EndPoint, false);//поддерживается и асинхронное подключение // Мы подключились? if (oscarClient.IsConnected) { // Запустим механизм асинхронного получения и отправки пакетов. // после этого нельзя использовать метод Receive() для получения пакета, // и более нельзя будет использовать Send() что бы отправить пакет моментально. oscarClient.RunAsyncProcessing(); // Например, отправим пакет var flap = FLAPHeader.Empty; byte[] d = Encoding.UTF8.GetBytes("Hello!"); oscarClient.Send(ref flap, d); } // Ждем нажатия Enter для завершения и выхода Console.Title = "[ENTER] to stop & exit"; Console.ReadLine(); // Отключим и уничтожим клиент if (oscarClient.IsConnected) oscarClient.Disconnect(0); oscarClient.Dispose(); // Остановим сервер stopServerExampleCode(); // Done return; #endregion X3: return; #region Пример использования OSCARUdp // Определим события для сервера var peerEventsServer = new OSCARCallbacks { Connected = (object sender, HostConnectEventArgs e) => { Console.WriteLine("[UDP Server] Accepted connection: " + e.Host); }, PacketReceived = (object sender, PacketEventArgs e) => { ((OSCARUdp)sender).Send(e.Host, e.Data); Console.WriteLine("[UDP Server] Packet from {0}, DataLength={1}", e.Host, e.Data.Length); } }; // Инициализируем пир "сервера" var peerServer = new OSCARUdp(2, peerEventsServer, true); peerServer.Start(IPAddress.Loopback);//Do not change to IPAddress.Any (only in this example) peerServer.RunAsyncProcessing(); Console.WriteLine("[UDP] Activated peerServer: " + ((IPEndPoint)peerServer.SocketBindAddress).Port); // Определим события для клиентов var peerEventsClient = new OSCARCallbacks { PacketReceived = (object sender, PacketEventArgs e) => { ((OSCARUdp)sender).Send(e.Host, e.Data); Console.WriteLine("[UDP Client] Packet: {0} DataLength={1}", e.FLAP, e.Data.Length); }, ConnectStarted = (object sender, HostEventArgs e) => { Console.WriteLine("[UDP Client] Connecting to {0}...", e.Host); }, ConnectFailed = (object sender, HostErrorEventArgs e) => { Console.WriteLine("[UDP Client] Connection failed: " + e.Error); }, Connected = (object sender, HostConnectEventArgs e) => { Console.WriteLine("[UDP Client] Connected to: " + e.Host); }, }; // Инициализируем первый пир "клиента" var peerClient = new OSCARUdp(2, peerEventsClient, false); peerClient.Start(); peerClient.RunAsyncProcessing(); Console.WriteLine("[UDP] Activated peerClient: " + ((IPEndPoint)peerClient.SocketBindAddress).Port); // Подключим еще один тестовый пир "клиента" к серверу var peerClient2 = new OSCARUdp(2, peerEventsClient, false); peerClient2.Start(); peerClient2.RunAsyncProcessing(); Console.WriteLine("[UDP] Activated peerClient2: " + ((IPEndPoint)peerClient2.SocketBindAddress).Port); // Подключим клиентов к серверу peerClient.Connect(peerServer.SocketBindAddress, false); peerClient2.Connect(peerServer.SocketBindAddress, false); // Отправим тестовое сообщение серверу var data = new byte[3000]; peerClient.Send(peerServer.SocketBindAddress, data); // Ждем нажатия Enter для завершения и выхода Console.Title = "[ENTER] to stop & exit"; Console.ReadLine(); // Остановим пиры и освободим ресурсы peerClient.Stop(); peerClient.Dispose(); peerClient2.Stop(); peerClient2.Dispose(); peerServer.Stop(); peerServer.Dispose(); #endregion X4: return; #region Пример использования ICQ Console.Write("ICQ UIN: "); var icqUin = Console.ReadLine(); Console.Write("ICQ Password: "******"{0}State changed: {1} => {2}", Environment.NewLine, e.OldState, e.NewState); if (e.Error != null) Console.WriteLine("{0}========================ERROR============================{0}{1}{0}============================{0}", Environment.NewLine, e.Error); }; // Подключимся к ICQ. icqClient.SignInAsync(); // Готово //Console.WriteLine("{0}{0}Press any key to exit.", Environment.NewLine); Console.ReadLine(); #endregion X5: #region Тестирование NetAsyncBuffer BufferPool pool = null; TcpClient tcp = null; EventHandler<SocketAsyncEventArgs> asyncOpEnd = (object sender, SocketAsyncEventArgs e) => { Console.WriteLine("Async operation finished."); pool.FreeBuffer(e); }; int bufferSize = ushort.MaxValue + FLAPHeader.FullLength; int bufferCount = 100; Console.WriteLine("Allocating buffer: x{0}*{1}...", bufferCount, bufferSize); pool = new BufferPool(asyncOpEnd, bufferSize, bufferCount); Console.WriteLine("Allocated."); Console.WriteLine("Connecting..."); tcp = new TcpClient(); tcp.Connect("login.icq.com", 5190); Console.WriteLine("ReceiveAsync called..."); tcp.Client.ReceiveAsync(pool.HoldBuffer(false, pool.BufferEntityLength)); Console.ReadLine(); #endregion }
/// <summary> /// Инициализирует новый экземпляр класса OSCAR для работы по протоколу на уровне TCP. /// </summary> /// <param name="appIDByte">Идентификатор приложения (FLAPHeader.ID)</param> /// <param name="events">Обработчик событий для этого экземпляра.</param> /// <param name="bindIp">IP-адрес для привязки сокета</param> /// <param name="bindPort">Порт для привязки сокета. 0 для случайного порта</param> public OSCAR(byte appIDByte, OSCARCallbacks events, IPAddress bindIp = null, ushort bindPort = 0) { AppIDByte = appIDByte; m_events = events; if (bindPort == 0) bindPort = (ushort)Misc.Random.Next(49152, ushort.MaxValue); m_bindAddr = new IPEndPoint(bindIp = IPAddress.Any, bindPort); m_events.InitializedInstance(this, EventArgs.Empty); m_localSequence = (ushort)Misc.Random.Next(0, ushort.MaxValue / 2); m_remoteSequence = 0; }
/// <summary> /// Инициализирует новый экземпляр класса OSCAR, позволяя вручную инициализировать сокет для работы. /// </summary> /// <param name="appIDByte">Идентификатор приложения (FLAPHeader.ID)</param> /// <param name="events">Обработчик событий для этого экземпляра.</param> /// <param name="sock">Экземпляр Socket для установки</param> /// <param name="triggerConnectEvent">True для вызова события Connected из конструктора</param> public OSCAR(byte appIDByte, OSCARCallbacks events, Socket sock, bool triggerConnectEvent) { AppIDByte = appIDByte; m_events = events; m_socket = sock; m_customSocket = true; m_remote = sock.RemoteEndPoint; if(triggerConnectEvent) m_events.Connected(this, new HostConnectEventArgs(sock.RemoteEndPoint, true)); m_localSequence = (ushort)Misc.Random.Next(0, ushort.MaxValue / 2); m_remoteSequence = 0; }