![]() |
Sylloge
A C# helper library
|
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 }