Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Communication.Data/SocketData.cs @ 1352

Last change on this file since 1352 was 705, checked in by abeham, 16 years ago

[TICKET #297] fixed some bugs in the TCP connection

File size: 7.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.IO;
25using System.Net;
26using System.Net.Sockets;
27using System.Text;
28using System.Xml;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31
32namespace HeuristicLab.Communication.Data {
33  public class SocketData : ItemBase, IDataStream {
34    private TcpNetworkDriverConfiguration config;
35    public IDriverConfiguration Configuration {
36      get { return config; }
37      set { config = (TcpNetworkDriverConfiguration)value; }
38    }
39
40    private TcpListener tcpListener;
41    private TcpClient tcpIn;
42    private TcpClient tcpOut;
43    private string buffer;
44
45    public SocketData() {
46      tcpListener = null;
47      tcpIn = null;
48      tcpOut = null;
49      config = null;
50      buffer = "";
51    }
52
53    #region clone & persistence
54    // A socket cannot be cloned
55    public override object Clone(IDictionary<Guid, object> clonedObjects) {
56      SocketData clone = new SocketData();
57      clonedObjects.Add(Guid, clone);
58      clone.tcpIn = tcpIn;
59      clone.config = (TcpNetworkDriverConfiguration)Auxiliary.Clone(config, clonedObjects);
60      clone.buffer = buffer;
61      return clone;
62    }
63
64    // A socket cannot be persisted
65    // but information can be persisted that will allow it to be recreated
66    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
67      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
68      XmlNode configNode = PersistenceManager.Persist("Configuration", config, document, persistedObjects);
69      node.AppendChild(configNode);
70      XmlNode bufferNode = document.CreateNode(XmlNodeType.Element, "Buffer", null);
71      bufferNode.InnerText = buffer;
72      node.AppendChild(bufferNode);
73      return node;
74    }
75
76    // A socket cannot be persisted
77    // but information can be persisted that will allow it to be recreated
78    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
79      base.Populate(node, restoredObjects);
80      Configuration = (TcpNetworkDriverConfiguration)PersistenceManager.Restore(node.SelectSingleNode("Configuration"), restoredObjects);
81      buffer = node.SelectSingleNode("Buffer").InnerText;
82      if (tcpListener == null) StartListening();
83    }
84    #endregion
85
86    private void StartListening() {
87      tcpListener = new TcpListener(IPAddress.Any, config.SourcePort.Data);
88      tcpListener.Start();
89    }
90
91    public void Initialize(IDriverConfiguration configuration) {
92      Configuration = configuration;
93      StartListening();
94    }
95
96    public bool Connect() {
97      if (!Alive(tcpIn)) {
98        if (tcpListener.Pending())
99          tcpIn = tcpListener.AcceptTcpClient();
100      }
101      if (!Alive(tcpOut)) {
102        tcpOut = new TcpClient();
103        try {
104          tcpOut.Connect(new IPEndPoint(IPAddress.Parse(config.TargetIPAddress.Data), config.TargetPort.Data));
105        } catch (SocketException) {
106          tcpOut.Close();
107          tcpOut = null;
108        }
109      }
110      return (tcpIn != null && tcpIn.Connected) && (tcpOut != null && tcpOut.Connected);
111    }
112
113    public void Close() {
114      if (tcpOut != null && tcpOut.Connected) {
115        tcpOut.Client.Close();
116        tcpOut.Close();
117      }
118      tcpOut = null;
119      if (tcpIn != null && tcpIn.Connected) {
120        tcpIn.Client.Close();
121        tcpIn.Close();
122      }
123      tcpIn = null;
124      tcpListener.Stop();
125      buffer = "";
126    }
127
128    public void Write(string s) {
129      //if (tcpOut == null || !tcpOut.Connected) Connect();
130      NetworkStream outStream = tcpOut.GetStream();
131
132      byte[] sendBytes = Encoding.ASCII.GetBytes(s + "\n.\n");
133      outStream.Write(sendBytes, 0, sendBytes.Length);
134      outStream.Flush();
135      return;
136    }
137
138    public string Read() {
139      //if (tcpIn == null || !tcpIn.Connected) Connect();
140      NetworkStream inStream = tcpIn.GetStream();
141      byte[] receivedBytes;
142      int count = 0;
143      int messageEnd = -1;
144      int bufferCount = 0;
145      if (buffer.Length > 0) {
146        byte[] bufferBytes = Encoding.ASCII.GetBytes(buffer);
147        receivedBytes = new byte[1000 + bufferBytes.Length];
148        Array.Copy(bufferBytes, receivedBytes, bufferBytes.Length);
149        messageEnd = TerminationCheck(receivedBytes, 0, bufferBytes.Length);
150        count = bufferBytes.Length;
151        bufferCount = count;
152        buffer = "";
153      } else
154        receivedBytes = new byte[1000];
155
156      if (messageEnd < 0) {
157        byte[] tmp = new byte[1000];
158        bool done;
159        do {
160          int recvd = inStream.Read(tmp, 0, 1000);
161          if (recvd == 0) break;
162          count += recvd;
163          if (count > receivedBytes.Length) {
164            byte[] h = receivedBytes;
165            receivedBytes = new byte[2 * h.Length];
166            Array.Copy(h, receivedBytes, count - recvd);
167          }
168          Array.Copy(tmp, 0, receivedBytes, count - recvd, recvd);
169          if (count < 3) done = false;
170          else done = (receivedBytes[count - 1] == 10 && receivedBytes[count - 2] == 46 && receivedBytes[count - 3] == 10); // \n.\n
171        } while (!done);
172        messageEnd = TerminationCheck(receivedBytes, bufferCount, count - bufferCount);
173      }
174      if (messageEnd < 0) throw new InvalidOperationException("ERROR: message was not received");
175      if (messageEnd < count - 3)
176        buffer = Encoding.ASCII.GetString(receivedBytes, messageEnd + 3, count - messageEnd - 3);
177      return Encoding.ASCII.GetString(receivedBytes, 0, messageEnd);
178    }
179
180    private int TerminationCheck(byte[] buffer, int start, int length) {
181      for (int i = start ; i < start + length - 2 ; i++) {
182        if (buffer[i] == 10 && buffer[i + 1] == 46 && buffer[i + 2] == 10) return i;
183      }
184      return -1;
185    }
186
187    private bool Alive(TcpClient c) {
188      if (c == null || !c.Connected) return false; // not connected if null or the property says so
189      try {
190        c.Client.Send(new byte[1], 0, 0); // if c != null && c.Connected make a zero byte send to check if still alive
191      } catch (SocketException e) {
192        return e.NativeErrorCode.Equals(10035); // 10035 == WSAEWOULDBLOCK, if true then connected, otherwise not connected
193      } catch (Exception) { // false regarding any other exception
194        return false;
195      }
196      return c.Connected; // return the property
197    }
198  }
199}
Note: See TracBrowser for help on using the repository browser.