/// <summary> /// Метод для асинхронной отправки данных сокету /// </summary> /// <param name="data">Данные</param> /// <param name="socketTo">Сокет, которому отправляются данные</param> /// <returns>True - в случае успешной отправки</returns> protected bool Send(byte[] data, Socket socketTo) { try { if (!socketTo.Connected) { return(false); } TcpSocketAsyncEventArgs e = poolEventArgs.Pop(); e.AcceptSocket = socketTo; if (e.Buffer == null) { e.SetBuffer(data, 0, data.Length); } #if DEBUG if (isLogging) { WriteToLog(string.Concat("Sending ", data.Length, " bytes")); } #endif if (!e.Socket.SendAsync(e)) { ProcessSend(e); } } catch (System.Exception ex) { SetException(ex, "TcpSocket.Send(byte[] data):"); return(false); } return(true); }
// Обработчик событий сокета /// <summary> /// Асинхронный обработчик событий сокета /// </summary> /// <param name="sender">Объект, для которого произошло событие</param> /// <param name="e">Параметр с текущим состоянием сокета</param> protected void OnSocketAsyncEventArgsCompleted(object sender, SocketAsyncEventArgs e) { TcpSocketAsyncEventArgs ee = (TcpSocketAsyncEventArgs)e; //#if DEBUG // if (isLogging) // WriteToLog("OnSocketAsyncEventArgsCompleted(Tobject sender, SocketAsyncEventArgs e): LastOperation = " + e.LastOperation + @", SocketError = " + e.SocketError); //#endif if (e.SocketError != SocketError.Success) { SetError(string.Concat("LastOperation =", e.LastOperation, ", SocketError=", e.SocketError), "TcpSocket.OnSocketAsyncEventArgsCompleted(object sender, SocketAsyncEventArgs e):"); ProcessError(ee); return; } // Определяем, какой тип операции был завершен и вызываем соответствующий обработчик switch (e.LastOperation) { case SocketAsyncOperation.Accept: ProcessAccept(ee); break; case SocketAsyncOperation.Connect: ProcessConnect(ee); break; case SocketAsyncOperation.Disconnect: ProcessDisconnect(ee); break; case SocketAsyncOperation.Receive: ProcessReceive(ee); break; case SocketAsyncOperation.Send: ProcessSend(ee); break; default: ProcessOther(ee); break; } }
/// <summary> /// Метод реализует цикл асинхронной обработки входящих подключений /// </summary> private void LoopProcessAccept() { while (IsStarted) { listenEvent.Reset(); TcpSocketAsyncEventArgs e = poolEventArgs.Pop(); try { if (e != null) { if (!socket.AcceptAsync(e)) { ProcessAccept(e, true); } } else { System.Diagnostics.Debug.Write("socket.AcceptAsync(e): e == null !!!"); } } catch (Exception ex) { System.Diagnostics.Debug.Write(ex.Message); } listenEvent.WaitOne(); } }
/// <summary> /// Извлечение объекта аргументов для асинхронного сокета из стека /// </summary> /// <returns></returns> public TcpSocketAsyncEventArgs Pop() { TcpSocketAsyncEventArgs result = null; //We are locking the stack, but we could probably use a ConcurrentStack if // we wanted to be fancy lock (syncObject) { if (stackSocketAsyncEventArgs.Count > 0) { result = stackSocketAsyncEventArgs.Pop(); result.Clear(); Interlocked.Increment(ref countEventsLock); } if (newSocketAsyncEventArgs != null) { result = newSocketAsyncEventArgs(); Interlocked.Increment(ref countEventsLock); } #if DEBUG if (isLogging) { WriteToLog("PoolSocketAsyncEventArgs.Pop(): CountLock = " + CountEventsLock); } #endif } if (result != null) { result.AcceptSocket = null; result.SocketError = SocketError.Success; result.RemoteEndPoint = null; result.UserToken = null; } return(result); }
/// <summary> /// Внутренняя функция создания нового объекта аргументов для асинхронного сокета /// </summary> /// <returns></returns> private TcpSocketAsyncEventArgs NewSocketAsyncEventArgs() { TcpSocketAsyncEventArgs e = (newSocketAsyncEventArgs != null ? newSocketAsyncEventArgs() : new TcpSocketAsyncEventArgs()); count++; e.Num = count; e.Completed += onSocketAsyncEventArgsCompleted; return(e); }
private void DisposeItem(TcpSocketAsyncEventArgs e) { if (disposeSocketAsyncEventArgs != null) { disposeSocketAsyncEventArgs(e); } e.Completed -= onSocketAsyncEventArgsCompleted; e.Dispose(); }
/// <summary> /// Обработка асинхронного события при завершении операции отправки данных серверу /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected virtual void ProcessSend(TcpSocketAsyncEventArgs e) { #if DEBUG if (isLogging) { WriteToLog(string.Concat("ProcessSend: Send ", e.BytesTransferred, " bytes")); } #endif OnSendHandle(e); }
/// <summary> /// Обработка асинхронного события, для которого не назначен обработчик /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected override void ProcessOther(TcpSocketAsyncEventArgs e) { #if DEBUG if (isLogging) { WriteToLog("ProcessOther"); } #endif base.ProcessOther(e); poolEventArgs.Push(e); }
public void CloseConnection(TcpSocketAsyncEventArgs e) { #if DEBUG if (isLogging) { WriteToLog("ProcessReceive: Connection closed."); } #endif e.CloseSocket(); e.Socket.Dispose(); poolEventArgs.Push(e); }
/// <summary> /// Обработка асинхронного события при возникновении ошибки /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected virtual void ProcessError(TcpSocketAsyncEventArgs e) { // В случае ошибки всегда возвращаем в пул объект события CloseConnection(e); poolEventArgs.Push(e); #if DEBUG if (isLogging) { WriteToLog("ProcessError(TcpSocketAsyncEventArgs e): CountPool = " + poolEventArgs.CountEventsLock); } #endif }
private void HandleDpasProtocol(TcpSocketAsyncEventArgs e, byte[] data) { if (dpasProtocol == null) { dpasProtocol = new DpasProtocol() { BufferSize = this.Settings.BufferSize } } ; dpasProtocol.Handle(e, data); }
// This method is triggered when the accept socket completes an operation async // In the case of our accept socket, we are looking for a client connection to complete // This method is used to process the accept socket connection protected void ProcessAccept(TcpSocketAsyncEventArgs e, bool fromAccept) { #if DEBUG if (isLogging) { WriteToLog(string.Concat("ProcessAccept (fromAccept=", fromAccept, ", e.Socket.Connected=", e.Socket.Connected, ", e.Buffer.Length=", e.Buffer == null ? 0 : e.Buffer.Length, ")")); } #endif listenEvent.Set(); // If the accept socket is connected to a client we will process it // otherwise nothing happens if (e.Socket.Connected) { try { if (e.BytesTransferred > 0) { #if DEBUG if (isLogging) { WriteToLog("ProcessAccept: acceptSocket.BytesTransferred > 0"); } #endif ProcessReceive(e); } else { #if DEBUG if (isLogging) { WriteToLog("ProcessAccept: acceptSocket.ReceiveAsync()"); } #endif //e.SetBuffer(new byte[Settings.BufferSize], 0, Settings.BufferSize); e.SetBuffer(new byte[Settings.BufferSize], 0, Settings.BufferSize); // Start a receive request and immediately check to see if the receive is already complete // Otherwise OnIOCompleted will get called when the receive is complete if (!e.Socket.ReceiveAsync(e)) { ProcessReceive(e); } } } catch (Exception ex) { SetException(ex, "TcpServer.ProcessAccept():"); } //// Start the process again to wait for the next connection //StartProcessAccept(AsyncEventArgs); } }
private void HandleHttpProtocol(TcpSocketAsyncEventArgs e, byte[] data) { DumpData(data); if (httpProtocol == null) { httpProtocol = new HttpProtocol(this) { BufferSize = Settings.BufferSize } } ; httpProtocol.Handle(e, data); }
/// <summary> /// Обработка асинхронного события при возникновении ошибки /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected override void ProcessError(TcpSocketAsyncEventArgs e) { #if DEBUG if (isLogging) { WriteToLog("ProcessError"); } #endif if (e.LastOperation == SocketAsyncOperation.Connect) { Disconnect(); } base.ProcessError(e); }
static byte[] DPAS = Encoding.ASCII.GetBytes("DPAS");//.UTF8.GetBytes("DPAS"); protected override void OnReceiveHandle(TcpSocketAsyncEventArgs e) { byte[] data = e.ToArray(); if (data[0] == DPAS[0] && data[1] == DPAS[1] && data[2] == DPAS[2] && data[3] == DPAS[3]) { HandleDpasProtocol(e, data); } else { HandleHttpProtocol(e, data); // Для Http закрываем соединение, как только произведем обработку //CloseProcessReceive(e); } }
/// <summary> /// Обработка асинхронного события при завершении операции отключения от сервера /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected override void ProcessDisconnect(TcpSocketAsyncEventArgs e) { #if DEBUG if (isLogging) { WriteToLog("ProcessDisconnect"); } #endif base.ProcessDisconnect(e); if (OnDisconnect != null) { OnDisconnect(this, e); } poolEventArgs.Push(e); }
/// <summary> /// Обработка события чтения данных из сокета /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected virtual void ProcessReceive(TcpSocketAsyncEventArgs e) { // Если количество переданных байтов 0 или принимающий сокет удален, то закроем соединение if (e.BytesTransferred == 0 || socket == null) { if (isLogging) { WriteToLog(string.Concat("ProcessReceive -> e.BytesTransferred == 0 || socket == null")); } CloseConnection(e); return; } e.Read(); #if DEBUG if (isLogging) { WriteToLog(string.Concat("ProcessReceive Num=", e.Num, ", Available=", e.Socket.Available, ", BytesTransferred=", e.BytesTransferred, ", Offset=", e.Offset, ", Count=", e.Count)); } #endif // Прочитаны все данные, можем их теперь обработать if (e.Socket.Available == 0) { if (isLogging) { WriteToLog(string.Concat("ProcessReceive END: Num=", e.Num, ", Available=", e.Socket.Available, ", BytesTransferred=", e.BytesTransferred, ", Offset=", e.Offset, ", Count=", e.Count)); } //e.IsClear = true; OnReceiveHandle(e); //if (e.IsClear) e.Clear(); } // и продолжаем читать дальше if (!e.IsClosed) { if (!e.Socket.ReceiveAsync(e)) { ProcessReceive(e); } } }
/// <summary> /// Возвращение объекта аргументов для асинхронного сокета в стек /// </summary> /// <param name="item"></param> public void Push(TcpSocketAsyncEventArgs e) { if (e == null) { throw new ArgumentNullException("Cannot add null object to socket stack"); } lock (stackSocketAsyncEventArgs) { Interlocked.Decrement(ref countEventsLock); DisposeItem(e); stackSocketAsyncEventArgs.Push(NewSocketAsyncEventArgs()); #if DEBUG if (isLogging) { WriteToLog("PoolSocketAsyncEventArgs.Push(): CountLock = " + CountEventsLock); } #endif } }
/// <summary> /// Пподключение к серверу. /// </summary> /// <returns>True - в случае успешного завершения</returns> private bool Connect() { if (!CreateSocket(Settings.Server, Settings.Port)) { return(false); } InitClient(); try { TcpSocketAsyncEventArgs e = poolEventArgs.Pop(); e.RemoteEndPoint = endpoint; socket.ConnectAsync(e); } catch (Exception ex) { SetException(ex, "TcpClient.Connect():"); return(false); } return(true); }
protected virtual void OnReceiveHandle(TcpSocketAsyncEventArgs e) { OnReceive?.Invoke(this, e); }
/// <summary> /// Обработка асинхронного события при получении нового подключения /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected virtual void ProcessAccept(TcpSocketAsyncEventArgs e) { }
/// <summary> /// Обработка асинхронного события при завершении операции отключения от сервера /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected virtual void ProcessDisconnect(TcpSocketAsyncEventArgs e) { }
protected override void ProcessAccept(TcpSocketAsyncEventArgs e) { ProcessAccept(e, false); }
/// <summary> /// Обработка асинхронного события, для которого не назначен обработчик /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected virtual void ProcessOther(TcpSocketAsyncEventArgs e) { }
// Используется только для отладки // protected override void ProcessReceive(TcpSocketAsyncEventArgs e) // { //#if DEBUG // if (isLogging) // WriteToLog("ProcessReceive"); //#endif // base.ProcessReceive(e); // } /// <summary> /// Обработка события при завершении асинхронной операции отправки данных серверу /// </summary> /// <param name="e">Параметр с текущим состоянием сокета</param> protected override void ProcessSend(TcpSocketAsyncEventArgs e) { base.ProcessSend(e); // Стартуем чтение данных от сервера e.Socket.ReceiveAsync(e); }
protected virtual void OnSendHandle(TcpSocketAsyncEventArgs e) { OnSend?.Invoke(this, e); }