/Transportation/TcpServerTransport.cs
C# | 195 lines | 141 code | 17 blank | 37 comment | 17 complexity | 108753ced4f619b3402e35dcd756687c MD5 | raw file
Possible License(s): AGPL-3.0
- using Datacollector.Configuration;
- using Datacollector.Transportation.AsyncStates;
- using Internationalization;
- using Logging;
- using ProbeNet.Backend;
- /*
- * The base library for collecting data from measurement devices
- * Copyright (C) Wolfgang Silbermayr
- * Copyright (C) Florian Marchl
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- using System;
- using System.Net;
- using System.Net.Sockets;
- namespace Datacollector.Transportation
- {
- /// <summary>
- /// Transport for using TCP server connection.
- /// </summary>
- [TranslatableCaption(Constants.DataCollectorDomain, "TCP connection, server on this computer")]
- [TransportTypeIdentifier("TcpServerTransport")]
- public class TcpServerTransport : Transport
- {
- private Socket listenSocket;
- private Socket dataSocket;
- /// <summary>
- /// Initializes a new instance of the <see cref="Datacollector.Transportation.TcpServerTransport"/> class.
- /// </summary>
- /// <param name="handle">Handle.</param>
- public TcpServerTransport(Handle handle)
- {
- Port = 8080;
- }
- /// <summary>
- /// Gets or sets the TCP port.
- /// </summary>
- /// <value>The port.</value>
- public int Port
- {
- get;
- set;
- }
- /// <inheritdoc/>
- protected override void Connect()
- {
- State = ConnectionState.Connecting;
- listenSocket = new Socket(AddressFamily.InterNetwork,
- SocketType.Stream,
- ProtocolType.Tcp);
- IPAddress hostIp = IPAddress.Any;
- IPEndPoint endPoint = new IPEndPoint(hostIp, Port);
- listenSocket.Bind(endPoint);
- listenSocket.Listen(1);
- BeginAccept();
- }
- private void BeginAccept()
- {
- State = ConnectionState.Connected;
- try {
- listenSocket.BeginAccept(OnSocketAccept, null);
- } catch (ObjectDisposedException) {
- // silently ignore, this happens when shutting down the interface
- State = ConnectionState.Disconnected;
- }
- }
- private void OnSocketAccept(IAsyncResult result)
- {
- try {
- dataSocket = listenSocket.EndAccept(result);
- SocketReceiveState receiveState = new SocketReceiveState(dataSocket, 1024);
- BeginReceive(receiveState);
- State = ConnectionState.Connected;
- } catch (ObjectDisposedException) {
- // silently ignore, this happens when shutting down the interface
- State = ConnectionState.Disconnected;
- } catch (Exception e) {
- NotifyExceptionCaught(e);
- }
- }
- private void BeginReceive(SocketReceiveState receiveState)
- {
- receiveState.Socket.BeginReceive(receiveState.Buffer, 0, receiveState.Buffer.Length, SocketFlags.None, OnDataReceived, receiveState);
- }
- private void OnDataReceived(IAsyncResult result)
- {
- SocketReceiveState receiveState = result.AsyncState as SocketReceiveState;
- int count = 0;
- try {
- count = receiveState.Socket.EndReceive(result);
- if (count != 0) {
- byte[] buffer = new byte[count];
- Array.Copy(receiveState.Buffer, buffer, count);
- NotifyDataReceived(buffer);
- }
- } catch (SocketException e) {
- if (e.SocketErrorCode == SocketError.ConnectionReset) {
- Logger.Error("TCP Server: remote end disconnected, waiting for incoming connection");
- }
- } catch (Exception e) {
- NotifyExceptionCaught(e);
- } finally {
- if (count == 0) {
- BeginAccept();
- } else {
- BeginReceive(receiveState);
- }
- }
- }
- /// <inheritdoc/>
- protected override void Disconnect()
- {
- State = ConnectionState.Disconnecting;
- if (dataSocket != null && dataSocket.Connected) {
- dataSocket.Shutdown(SocketShutdown.Both);
- dataSocket.Close();
- }
- listenSocket.Close();
- State = ConnectionState.Disconnected;
- }
- /// <inheritdoc/>
- public override void SendData(byte[] data, int offset, int count)
- {
- if (dataSocket == null || !dataSocket.Connected) {
- throw new InvalidOperationException("The socket you want to send data on is not connected");
- }
- Logger.Log("sending: {0}", System.Text.Encoding.ASCII.GetString(data, offset, count));
- dataSocket.BeginSend(data, offset, count, SocketFlags.None, OnDataSent, null);
- }
- private void OnDataSent(IAsyncResult result)
- {
- if (dataSocket.Connected) {
- try {
- dataSocket.EndSend(result);
- } catch (SocketException e) {
- if (e.SocketErrorCode == SocketError.Shutdown) {
- // silently ignore, this happens when the other end disconnects
- State = ConnectionState.Connecting;
- } else {
- NotifyExceptionCaught(e);
- }
- } catch (Exception e) {
- NotifyExceptionCaught(e);
- }
- }
- }
- /// <inheritdoc/>
- public override DataSourceConfiguration<D> BuildDatasourceConfiguration<D>(D settings)
- {
- GenericDataSourceConfiguration<TcpServerTransportSettings, D> configuration =
- new GenericDataSourceConfiguration<TcpServerTransportSettings, D>(
- settings,
- new TcpServerTransportSettings() {
- Port = Port
- });
- return configuration as DataSourceConfiguration<D>;
- }
- /// <inheritdoc/>
- public override bool MustDeleteDataBeforeUse
- {
- get
- {
- return false;
- }
- }
- }
- }