/Transportation/TcpClientTransport.cs
C# | 214 lines | 154 code | 19 blank | 41 comment | 22 complexity | 80c8d8fda4b80c56fbc64c1d5405a9cd MD5 | raw file
Possible License(s): AGPL-3.0
- using Datacollector.Configuration;
- using Datacollector.Transportation.AsyncStates;
- using Internationalization;
- 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.NetworkInformation;
- using System.Net.Sockets;
- namespace Datacollector.Transportation
- {
- /// <summary>
- /// Transport for using the TCP client connection.
- /// </summary>
- [TranslatableCaption(Constants.DataCollectorDomain, "TCP connection, client on this computer")]
- [TransportTypeIdentifier("TcpClientTransport")]
- public class TcpClientTransport : Transport
- {
- private Socket socket;
- /// <summary>
- /// Initializes a new instance of the <see cref="Datacollector.Transportation.TcpClientTransport"/> class.
- /// </summary>
- /// <param name="handle">Handle.</param>
- public TcpClientTransport(Handle handle)
- {
- Address = "127.0.0.1";
- Port = 4001;
- }
- /// <summary>
- /// Gets or sets the TCP server address.
- /// </summary>
- /// <value>The address.</value>
- public string Address
- {
- get;
- set;
- }
- /// <summary>
- /// Gets or sets the TCP server port.
- /// </summary>
- /// <value>The port.</value>
- public int Port
- {
- get;
- set;
- }
- private IPAddress ParseIPAddress(string address)
- {
- IPAddress parsedAddress = IPAddress.Parse(address);
- if (parsedAddress.AddressFamily == AddressFamily.InterNetworkV6) {
- string[] parts = address.Split('%');
- if (parts.Length > 1) {
- string ifname = parts[1];
- int i = 1;
- foreach (NetworkInterface networkif in NetworkInterface.GetAllNetworkInterfaces()) {
- if (networkif.Name == ifname) {
- parsedAddress.ScopeId = i;
- }
- i++;
- }
- }
- }
- return parsedAddress;
- }
- /// Gets or sets the port.
- protected override void Connect()
- {
- if (State != ConnectionState.Disconnected) {
- throw new InvalidOperationException(String.Format(
- "Cannot only connect when the state is disconnected. Current state: {0}",
- State));
- }
- IPAddress parsedAddress = ParseIPAddress(Address);
- socket = new Socket(parsedAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
- socket.BeginConnect(parsedAddress, Port, OnConnected, null);
- State = ConnectionState.Connecting;
- }
- private void OnConnected(IAsyncResult result)
- {
- try {
- socket.EndConnect(result);
- SocketReceiveState receiveState = new SocketReceiveState(socket, 1024);
- BeginReceive(receiveState);
- State = ConnectionState.Connected;
- } catch (Exception e) {
- NotifyExceptionCaught(e);
- State = ConnectionState.Disconnected;
- }
- }
- private void BeginReceive(SocketReceiveState receiveState)
- {
- socket.BeginReceive(receiveState.Buffer, 0, receiveState.Buffer.Length, SocketFlags.None, OnDataReceived, receiveState);
- }
- private void OnDataReceived(IAsyncResult result)
- {
- try {
- SocketReceiveState receiveState = result.AsyncState as SocketReceiveState;
- int count = receiveState.Socket.EndReceive(result);
- if (count == 0) {
- // connection was shut down by remote end
- Disconnect();
- } else {
- byte[] buffer = new byte[count];
- Array.Copy(receiveState.Buffer, buffer, count);
- NotifyDataReceived(buffer);
- BeginReceive(receiveState);
- }
- } catch (SocketException e) {
- if (e.SocketErrorCode == SocketError.Interrupted) {
- // ignore, we are probably shutting down
- } else {
- NotifyExceptionCaught(e);
- }
- } catch (Exception e) {
- NotifyExceptionCaught(e);
- }
- }
- private void BeginReconnect()
- {
- State = ConnectionState.Disconnecting;
- socket.Disconnect(false);
- State = ConnectionState.Disconnected;
- Connect();
- }
- /// Gets or sets the port.
- protected override void Disconnect()
- {
- if (State == ConnectionState.Disconnected || State == ConnectionState.Disconnecting) {
- // ignore, we are already disconnecting
- return;
- }
- State = ConnectionState.Disconnecting;
- if (socket.Connected) {
- socket.Shutdown(SocketShutdown.Both);
- }
- socket = null;
- State = ConnectionState.Disconnected;
- }
- /// Gets or sets the port.
- public override void SendData(byte[] data, int offset, int count)
- {
- if (socket == null || !socket.Connected) {
- throw new InvalidOperationException("The socket you want to send data on is not connected");
- }
- socket.BeginSend(data, offset, count, SocketFlags.None, OnDataSent, null);
- }
- private void OnDataSent(IAsyncResult result)
- {
- try {
- if (socket.Connected) {
- socket.EndSend(result);
- }
- } catch (Exception e) {
- NotifyExceptionCaught(e);
- }
- }
- /// Gets or sets the port.
- public override DataSourceConfiguration<D> BuildDatasourceConfiguration<D>(D settings)
- {
- GenericDataSourceConfiguration<TcpClientTransportSettings, D> configuration =
- new GenericDataSourceConfiguration<TcpClientTransportSettings, D>(
- settings,
- new TcpClientTransportSettings() {
- Port = Port,
- Address = Address
- });
- return configuration as DataSourceConfiguration<D>;
- }
- /// Gets or sets the port.
- public override bool MustDeleteDataBeforeUse
- {
- get
- {
- return false;
- }
- }
- }
- }