Sylloge
A C# helper library
code/Net/Socket.cs
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 /*
00017 using System;
00018 using System.Collections.Generic;
00019 using System.Text;
00020 using System.Windows.Forms;
00021 using System.Net;
00022 using System.Runtime.InteropServices;
00023 using System.Collections;
00024 using System.Data;
00025 using System.Diagnostics;
00026 */
00027 
00028 namespace Sylloge
00029 {
00030     public static partial class Net
00031     {
00035         public const string IP_ADDRESS_UNDEFINED = "0.0.0.0";
00036 
00040         public abstract class Socket : System.IDisposable
00041         {
00045             public enum KeepAliveType
00046             {
00050                 NONE,
00054                 CUSTOM,
00058                 TCP
00059             }
00060 
00061             #region Events
00062 
00067             public delegate void DelegateDataReceived(byte[] data);
00071             public event DelegateDataReceived DataReceived;
00072 
00077             public delegate void DelegateSocketError(System.Exception ex);
00081             public event DelegateSocketError SocketError;
00082 
00087             public delegate void DelegateConnectionCloseError(System.Exception ex);
00091             public event DelegateConnectionCloseError ConnectionCloseError;
00092 
00097             protected void OnDataReceived(byte[] data)
00098             {
00099                 if (DataReceived != null) { DataReceived(data); }
00100             }
00101 
00106             protected void OnSocketError(System.Exception ex)
00107             {
00108                 if (SocketError != null) { SocketError(ex); }
00109             }
00110 
00115             protected void OnConnectionCloseError(System.Exception ex)
00116             {
00117                 if (ConnectionCloseError != null) { ConnectionCloseError(ex); }
00118             }
00119 
00120             #endregion
00121 
00122             #region Local Attributes
00123 
00127             protected System.IAsyncResult m_AsyncResult { get; private set; }
00131             protected System.Windows.Forms.Timer m_KeepAlive { get; set; }
00135             protected System.Threading.Thread m_ListenThread { get; set; }
00139             protected byte[] m_Msg { get; set; }
00143             protected KeepAliveType m_KeepAliveType { get; set; }
00144 
00148             public bool IsClosing { get; protected set; }
00152             public bool IsConnected { get; protected set; }
00156             public bool IsLocalHost { get; protected set; }
00160             public string IpAddress { get; set; }
00164             public bool IsRunning { get; protected set; }
00168             public int Port { get; set; }
00172             public System.Net.Sockets.Socket Handle { get; protected set; }
00176             public System.Net.Sockets.NetworkStream Stream { get; protected set; }
00177 
00178             #endregion
00179 
00180             #region Class Methods
00181 
00185             public Socket()
00186             {
00187                 this.Initialize();
00188             }
00189 
00195             public Socket(string ipAddress, int port)
00196             {
00197                 this.Initialize();
00198                 this.IpAddress = IpAddress;
00199                 this.Port = port;
00200             }
00201 
00205             ~Socket()
00206             {
00207                 if (this.IsConnected) { this.Close(); }
00208             }
00209 
00214             public virtual Sylloge.Net.Socket Copy()
00215             {
00216                 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter val =
00217                     new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
00218                 System.IO.MemoryStream s = new System.IO.MemoryStream();
00219                 val.Serialize(s, this);
00220                 Sylloge.Net.Socket res = (Sylloge.Net.Socket)val.Deserialize(s);
00221                 res.Close();
00222                 return res;
00223             }
00224 
00231             protected void Configure(KeepAliveType type, byte[] msg, int msInterval)
00232             {
00233                 this.m_KeepAliveType = type;
00234                 if (this.m_KeepAliveType == KeepAliveType.CUSTOM) {
00235                     if (msg != null && msg.Length > 0) {
00236                         this.m_Msg = new byte[msg.Length];
00237                         System.Buffer.BlockCopy(msg, 0, this.m_Msg, 0, msg.Length);
00238                     }
00239                 }
00240             }
00241 
00245             public void Dispose()
00246             {
00247                 if (this.IsConnected) { this.Close(); }
00248             }
00249 
00253             public void Flush()
00254             {
00255                 this.Stream.Flush();
00256             }
00257 
00261             public void Initialize()
00262             {
00263                 this.IpAddress = "0.0.0.0";
00264                 this.Port = 0;
00265                 this.IsClosing = false;
00266                 this.IsConnected = false;
00267                 this.IsRunning = false;
00268                 this.IsLocalHost = false;
00269             }
00270 
00274             public string IpAndPortString
00275             {
00276                 get
00277                 {
00278                     string Value = (this.IpAddress + ":" + this.Port.ToString());
00279                     if (this.IsLocalHost) { Value = "Local Machine"; }
00280                     return Value;
00281                 }
00282             }
00283 
00287             public void Shutdown()
00288             {
00289                 this.IsRunning = false;
00290                 if (this.IsClosing) { return; }
00291                 this.IsClosing = true;
00292                 if (this.IsLocalHost) { return; }
00293                 if (this.m_KeepAlive != null) { this.m_KeepAlive.Enabled = false; }
00294                 if (this.Handle != null) {
00295                     try {
00296                         this.Handle.Shutdown(System.Net.Sockets.SocketShutdown.Both);
00297                         this.Handle.Disconnect(true);
00298                         this.Handle.Close();
00299                     } catch (System.Exception ex) {
00300                         this.OnConnectionCloseError(ex);
00301                     }
00302                 }
00303                 this.IsConnected = false;
00304                 if (this.Stream != null) {
00305                     try {
00306                         this.Stream.Close();
00307                     } catch (System.Exception ex) {
00308                         this.OnConnectionCloseError(ex);
00309                     }
00310                 }
00311                 if (this.m_ListenThread != null) {
00312                     try {
00313                         this.m_ListenThread.Abort();
00314                     } catch (System.Threading.ThreadAbortException threadEx) {
00315                         System.Console.WriteLine("Thread abort exception: " + threadEx.Message);
00316                     } catch (System.Exception ex) {
00317                         this.OnConnectionCloseError(ex);
00318                     }
00319                 }
00320                 this.m_KeepAlive = null;
00321                 this.m_ListenThread = null;
00322             }
00323 
00328             public override string ToString()
00329             {
00330                 return this.IpAndPortString;
00331             }
00332 
00333             #endregion
00334 
00335             #region Virtual Methods
00336 
00340             public abstract void Close();
00341 
00348             public abstract void Connect(Socket.KeepAliveType type = KeepAliveType.NONE, byte[] msg = null, int msInterval = 0);
00349 
00353             public abstract void Listen();
00354 
00359             public abstract void Send(byte[] data);
00360 
00361             #endregion
00362         }
00363 
00364         public class TcpSocket : Sylloge.Net.Socket
00365         {
00369             public System.Net.Sockets.TcpClient Client { get; protected set; }
00373             public System.Net.Sockets.TcpListener Listener { get; protected set; }
00374 
00378             public TcpSocket()
00379             {
00380             }
00381 
00387             public TcpSocket(string ipAddress, int port)
00388             {
00389                 this.IpAddress = IpAddress;
00390                 this.Port = port;
00391             }
00392 
00397             public override Sylloge.Net.Socket Copy()
00398             {
00399                 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter val =
00400                     new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
00401                 System.IO.MemoryStream s = new System.IO.MemoryStream();
00402                 val.Serialize(s, this);
00403                 Sylloge.Net.Socket res = (Sylloge.Net.Socket)val.Deserialize(s);
00404                 res.Close();
00405                 return res;
00406             }
00407 
00411             public override void Close()
00412             {
00413                 if (this.Listener != null) {
00414                     try {
00415                         this.Listener.Stop();
00416                     } catch (System.Exception ex) {
00417                         this.OnConnectionCloseError(ex);
00418                     }
00419                 }
00420                 this.Shutdown();
00421                 if (this.Client != null) {
00422                     try {
00423                         this.Client.Close();
00424                     } catch (System.Exception ex) {
00425                         this.OnConnectionCloseError(ex);
00426                     }
00427                 }
00428                 this.Listener = null;
00429                 this.Client = null;
00430             }
00431 
00438             public override void Connect(Socket.KeepAliveType type = KeepAliveType.NONE, byte[] msg = null, int msInterval = 0)
00439             {
00440                 this.IsClosing = false;
00441                 try {
00442                     System.Net.IPAddress ipa = new System.Net.IPAddress(0);
00443                     System.Net.IPAddress.TryParse(this.IpAddress, out ipa);
00444                     try {
00445                         this.Client = new System.Net.Sockets.TcpClient();
00446                         this.Handle = this.Client.Client;
00447                         this.Client.Connect(ipa, this.Port);
00448                         this.Stream = this.Client.GetStream();
00449                     } catch (System.Exception ex) {
00450                         this.OnSocketError(ex);
00451                         return;
00452                     }
00453                 } catch (System.Exception ex) {
00454                     this.OnSocketError(ex);
00455                     return;
00456                 }
00457                 this.IsConnected = true;
00458                 this.Configure(type, msg, msInterval);
00459                 switch (type) {
00460                     case KeepAliveType.CUSTOM:
00461                         this.m_KeepAlive = new System.Windows.Forms.Timer();
00462                         this.m_KeepAlive.Tick += new System.EventHandler(this.TcpKeepAlive_Tick);
00463                         this.m_KeepAlive.Interval = msInterval;
00464                         this.m_KeepAlive.Enabled = true;
00465                         break;
00466                     case KeepAliveType.TCP:
00467                         this.Client.Client.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Tcp, System.Net.Sockets.SocketOptionName.KeepAlive, true);
00468                         break;
00469                 }
00470             }
00471 
00475             public override void Listen()
00476             {
00477                 this.IsClosing = false;
00478                 if (this.IsLocalHost) { return; }
00479                 try {
00480                     System.Net.IPAddress IPAddress = new System.Net.IPAddress(0);
00481                     System.Net.IPAddress.TryParse(this.IpAddress, out IPAddress);
00482                     try {
00483                         this.Listener = new System.Net.Sockets.TcpListener(IPAddress, this.Port);
00484                         this.Client = new System.Net.Sockets.TcpClient();
00485                         this.Handle = this.Client.Client;
00486                         this.Listener.Start();
00487                         this.Client = this.Listener.AcceptTcpClient();
00488                         System.Threading.ThreadStart ListenThreadStart = new System.Threading.ThreadStart(this.TcpListenerThread);
00489                         this.m_ListenThread = new System.Threading.Thread(ListenThreadStart);
00490                         this.IsRunning = true;
00491                         this.m_ListenThread.Start();
00492                         this.IsConnected = true;
00493                     } catch (System.Exception ex) {
00494                         this.OnSocketError(ex);
00495                     }
00496                 } catch (System.Exception ex) {
00497                     this.OnSocketError(ex);
00498                 }
00499             }
00500 
00504             private void TcpListenerThread()
00505             {
00506                 try {
00507                     byte[] ReceievedBytes = null;
00508                     do {
00509                         System.Windows.Forms.Application.DoEvents();
00510                         this.Stream = this.Client.GetStream();
00511                         ReceievedBytes = new byte[this.Client.ReceiveBufferSize];
00512                         this.Stream.Read(ReceievedBytes, 0, this.Client.ReceiveBufferSize);
00513                         this.OnDataReceived(ReceievedBytes);
00514                     } while (this.IsRunning);
00515                 } catch (System.Threading.ThreadAbortException threadEx) {
00516                     System.Console.WriteLine("Thread aborting: " + threadEx.Message);
00517                 } catch (System.Exception ex) {
00518                     this.OnSocketError(ex);
00519                 }
00520                 this.IsConnected = false;
00521             }
00522 
00527             public override void Send(byte[] data)
00528             {
00529                 try {
00530                     this.Stream.Write(data, 0, data.Length);
00531                     this.Stream.Flush();
00532                 } catch (System.Exception ex) {
00533                     System.Console.WriteLine("Error sending data: " + ex.Message);
00534                     this.OnSocketError(ex);
00535                 }
00536             }
00537 
00543             private void TcpKeepAlive_Tick(object sender, System.EventArgs e)
00544             {
00545                 if (this.IsConnected && this.Client.Connected && this.Stream != null) {
00546                     try {
00547                         this.Stream.Write(this.m_Msg, 0, this.m_Msg.Length); // send null bytes to keep alive
00548                     } catch (System.Exception ex) {
00549                         this.OnSocketError(ex);
00550                     }
00551                 }
00552             }
00553 
00558             public override string ToString()
00559             {
00560                 return this.IpAndPortString;
00561             }
00562         }
00563 
00564         public class UdpSocket : Sylloge.Net.Socket
00565         {
00569             public System.Net.Sockets.UdpClient Client { get; protected set; }
00570 
00574             public UdpSocket()
00575             {
00576             }
00577 
00583             public UdpSocket(string ipAddress, int port)
00584             {
00585                 this.IpAddress = IpAddress;
00586                 this.Port = port;
00587             }
00588 
00593             public override Sylloge.Net.Socket Copy()
00594             {
00595                 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter val =
00596                     new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
00597                 System.IO.MemoryStream s = new System.IO.MemoryStream();
00598                 val.Serialize(s, this);
00599                 Sylloge.Net.Socket res = (Sylloge.Net.Socket)val.Deserialize(s);
00600                 res.Close();
00601                 return res;
00602             }
00603 
00607             public override void Close()
00608             {
00609                 this.Shutdown();
00610                 if (this.Client != null) {
00611                     try {
00612                         this.Client.Close();
00613                     } catch (System.Exception ex) {
00614                         this.OnConnectionCloseError(ex);
00615                     }
00616                 }
00617                 this.Client = null;
00618             }
00619 
00626             public override void Connect(Socket.KeepAliveType type = KeepAliveType.NONE, byte[] msg = null, int msInterval = 0)
00627             {
00628                 this.IsClosing = false;
00629                 System.Net.Sockets.UdpClient x = new System.Net.Sockets.UdpClient();
00630                 try {
00631                     System.Net.IPAddress ipad = new System.Net.IPAddress(0);
00632                     System.Net.IPAddress.TryParse(this.IpAddress, out ipad);
00633                     try {
00634                         this.Client = new System.Net.Sockets.UdpClient();
00635                         this.Handle = this.Client.Client;
00636                         this.Client.Connect(ipad, this.Port);
00637                         // TODO: verify this!!!
00638                         this.IsConnected = (this.Client.Client.Connected && this.Client.Client.IsBound);
00639                         //this.IsConnected = true;
00640                     } catch (System.Exception ex) {
00641                         this.OnSocketError(ex);
00642                     }
00643                 } catch (System.Exception ex) {
00644                     this.OnSocketError(ex);
00645                 }
00646                 switch (type) {
00647                     case KeepAliveType.CUSTOM:
00648                         this.m_KeepAlive = new System.Windows.Forms.Timer();
00649                         this.m_KeepAlive.Tick += new System.EventHandler(this.UdpKeepAlive_Tick);
00650                         this.m_KeepAlive.Interval = msInterval;
00651                         this.m_KeepAlive.Enabled = true;
00652                         break;
00653                     case KeepAliveType.TCP:
00654                         throw new System.ArgumentException("Cannot specify TCP keep alive type for UDP socket");
00655                         //break;
00656                 }
00657                 this.Configure(type, msg, msInterval);
00658             }
00659 
00663             public override void Listen()
00664             {
00665                 this.IsClosing = false;
00666                 if (this.IsLocalHost) { return; }
00667                 try {
00668                     try {
00669                         this.Client = new System.Net.Sockets.UdpClient(this.Port, System.Net.Sockets.AddressFamily.InterNetwork);
00670                         this.Handle = this.Client.Client;
00671                         System.Threading.ThreadStart ListenThreadStart = new System.Threading.ThreadStart(this.UdpListenerThread);
00672                         this.m_ListenThread = new System.Threading.Thread(ListenThreadStart);
00673                         this.IsRunning = true;
00674                         this.m_ListenThread.Start();
00675                         this.IsConnected = true;
00676                     } catch (System.Exception ex) {
00677                         this.OnSocketError(ex);
00678                     }
00679                 } catch (System.Exception ex) {
00680                     this.OnSocketError(ex);
00681                 }
00682             }
00683 
00687             private void UdpListenerThread()
00688             {
00689                 try {
00690                     byte[] ReceievedBytes = null;
00691                     System.Net.IPAddress ipad = new System.Net.IPAddress(0);
00692                     System.Net.IPAddress.TryParse(this.IpAddress, out ipad);
00693                     System.Net.IPEndPoint udpep = new System.Net.IPEndPoint(ipad, this.Port);
00694                     do {
00695                         System.Windows.Forms.Application.DoEvents();
00696                         ReceievedBytes = this.Client.Receive(ref udpep);
00697                         this.OnDataReceived(ReceievedBytes);
00698                         System.Windows.Forms.Application.DoEvents();
00699                     } while (this.IsRunning);
00700                 } catch (System.Threading.ThreadAbortException threadEx) {
00701                     System.Console.WriteLine("Thread aborting: " + threadEx.Message);
00702                 } catch (System.Exception ex) {
00703                     this.OnSocketError(ex);
00704                 }
00705                 this.IsConnected = false;
00706             }
00707 
00712             public override void Send(byte[] data)
00713             {
00714                 try {
00715                     this.Client.Send(data, data.Length);
00716                 } catch (System.Exception ex) {
00717                     System.Console.WriteLine("Error sending data: " + ex.Message);
00718                     this.OnSocketError(ex);
00719                 }
00720             }
00721 
00727             private void UdpKeepAlive_Tick(object sender, System.EventArgs e)
00728             {
00729                 if (this.IsConnected && this.Client != null && this.Client.Client.Connected) {
00730                     try {
00731                         this.Client.Client.Send((new byte[] { 0x01 }));
00732                     } catch (System.Exception ex) {
00733                         this.OnSocketError(ex);
00734                     }
00735                 }
00736             }
00737 
00742             public override string ToString()
00743             {
00744                 return this.IpAndPortString;
00745             }
00746         }
00747     }
00748 }
 All Classes Namespaces Files Functions Variables Enumerations Properties Events