Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3.1/sources/HeuristicLab.Communication.Data/SocketData.cs @ 1893

Last change on this file since 1893 was 592, checked in by abeham, 16 years ago

Put the GPL license in the files from the communication framework and simulation optimization project (branch 3.1)

File size: 6.9 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 (tcpIn == null || !tcpIn.Connected) {
98        if (tcpListener.Pending())
99          tcpIn = tcpListener.AcceptTcpClient();
100      }
101      if (tcpOut == null || !tcpOut.Connected) {
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      tcpListener.Stop();
115      if ((tcpOut != null && tcpOut.Connected) && (tcpIn != null && tcpIn.Connected)) {
116        Write("CLOSING");
117        if (Read() != null)
118          throw new InvalidOperationException("ERROR in SocketData: Out of sync during Close()");
119      }
120      if (tcpIn != null) {
121        tcpIn.Close();
122        tcpIn = null;
123      }
124      if (tcpOut != null) {
125        tcpOut.Close();
126        tcpOut = null;
127      }
128      buffer = "";
129    }
130
131    public void Write(string s) {
132      if (tcpOut == null || !tcpOut.Connected) Connect();
133      NetworkStream outStream = tcpOut.GetStream();
134
135      byte[] sendBytes = Encoding.ASCII.GetBytes(s + "\n.\n");
136      outStream.Write(sendBytes, 0, sendBytes.Length);
137      outStream.Flush();
138      return;
139    }
140
141    public string Read() {
142      if (tcpIn == null || !tcpIn.Connected) Connect();
143      NetworkStream inStream = tcpIn.GetStream();
144      byte[] receivedBytes;
145      int count = 0;
146      int messageEnd = -1;
147      int bufferCount = 0;
148      if (buffer.Length > 0) {
149        byte[] bufferBytes = Encoding.ASCII.GetBytes(buffer);
150        receivedBytes = new byte[1000 + bufferBytes.Length];
151        Array.Copy(bufferBytes, receivedBytes, bufferBytes.Length);
152        messageEnd = TerminationCheck(receivedBytes, 0, bufferBytes.Length);
153        count = bufferBytes.Length;
154        bufferCount = count;
155        buffer = "";
156      } else
157        receivedBytes = new byte[1000];
158
159      if (messageEnd < 0) {
160        byte[] tmp = new byte[1000];
161        bool done;
162        do {
163          int recvd = inStream.Read(tmp, 0, 1000);
164          if (recvd == 0) break;
165          count += recvd;
166          if (count > receivedBytes.Length) {
167            byte[] h = receivedBytes;
168            receivedBytes = new byte[2 * h.Length];
169            Array.Copy(h, receivedBytes, count - recvd);
170          }
171          Array.Copy(tmp, 0, receivedBytes, count - recvd, recvd);
172          if (count < 3) done = false;
173          else done = (receivedBytes[count - 1] == 10 && receivedBytes[count - 2] == 46 && receivedBytes[count - 3] == 10); // \n.\n
174        } while (!done);
175        messageEnd = TerminationCheck(receivedBytes, bufferCount, count - bufferCount);
176      }
177      if (messageEnd < 0) throw new InvalidOperationException("ERROR: message was not received");
178      if (messageEnd < count - 3)
179        buffer = Encoding.ASCII.GetString(receivedBytes, messageEnd + 3, count - messageEnd - 3);
180      string result = Encoding.ASCII.GetString(receivedBytes, 0, messageEnd);
181      if (result.Equals("CLOSING")) return null;
182      else return result;
183    }
184
185    private int TerminationCheck(byte[] buffer, int start, int length) {
186      for (int i = start ; i < start + length - 2 ; i++) {
187        if (buffer[i] == 10 && buffer[i + 1] == 46 && buffer[i + 2] == 10) return i;
188      }
189      return -1;
190    }
191  }
192}
Note: See TracBrowser for help on using the repository browser.