Thema: [C#] Multi-Client TCP Server
avsn-WorldRacer
avatar
Redaktion
Redaktion
Beiträge: 208

verfasst:
15.Sep 2010 - 14:09

Eine kleine Klasse, die einen Multi-Client Server implementiert.


Code
  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2. *  Copyright (C) Marco Klein alias WorldRacer, WorldRacer92, WorldRacer_original  *
  3. *                                                                                 *
  4. *   This program is free software: you can redistribute it and/or modify          *
  5. *   it under the terms of the GNU General Public License as published by          *
  6. *   the Free Software Foundation, either version 3 of the License, or             *
  7. *   (at your option) any later version.                                           *
  8. *                                                                                 *
  9. *   This program is distributed in the hope that it will be useful,               *
  10. *   but WITHOUT ANY WARRANTY; without even the implied warranty of                *
  11. *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
  12. *   GNU General Public License for more details.                                  *
  13. *                                                                                 *
  14. *   You should have received a copy of the GNU General Public License             *
  15. *   along with this program.  If not, see <http://www.gnu.org/licenses/>.         *
  16. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  17.  
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Linq;
  21. using System.Text;
  22.  
  23. namespace devNetworks
  24. {
  25.     /// <summary>
  26.     /// This class represents a client
  27.     /// </summary>
  28.     public class Client
  29.     {
  30.         #region Public Attributes
  31.         /// <summary>
  32.         /// Socket. (TcpClient)
  33.         /// </summary>
  34.         public System.Net.Sockets.TcpClient Socket
  35.         {
  36.             get { return _Socket; }
  37.             set { _Socket = value; }
  38.         }
  39.         #endregion
  40.  
  41.         #region Private Attributes
  42.  
  43.         // Thread for handling server Messages
  44.         System.Threading.Thread _ClientThread = null;
  45.  
  46.         // Socket to handle with
  47.         private System.Net.Sockets.TcpClient _Socket = null;
  48.  
  49.         // IP-Adress of the endpoint
  50.         private string _IPAdress = string.Empty;
  51.  
  52.         // Port to connect at the entpoint
  53.         private int _Port = 0;
  54.  
  55.         // Contains whether we are connected or not.
  56.         private bool _Connected = false;
  57.  
  58.         // Bufferlength
  59.         int _BufferLength = 4096;
  60.  
  61.         // Get a client stream for reading and writing.
  62.         //  Stream stream = client.GetStream();
  63.         System.Net.Sockets.NetworkStream _Stream;
  64.  
  65.         // How shall the messages be encoded to?
  66.         System.Text.Encoding _EncodingInstance = System.Text.Encoding.ASCII;
  67.         #endregion
  68.  
  69.         #region Constructor
  70.         /// <summary>
  71.         /// Initializes a Client
  72.         /// </summary>
  73.         /// <param name="IPAdress">IP-Adress of the endpoint</param>
  74.         /// <param name="Port">Port to connect at the entpoint</param>
  75.         /// <param name="ConnectImmediately">Should I connect directly?</param>
  76.         /// <param name="BufferLength">How long shall the received messages be?</param>
  77.         /// <param name="EncodingInstance">How shall the messages be encoded to?</param>       
  78.         public Client(string IPAdress, int Port, System.Text.Encoding EncodingInstance, bool ConnectImmediately = false, int BufferLength = 4096)
  79.         {
  80.             // Save the values
  81.             if (BufferLength > 0)
  82.             {
  83.                 _BufferLength = BufferLength;
  84.             }
  85.             else
  86.             {
  87.                 _BufferLength = 4096;
  88.             }
  89.            
  90.             _EncodingInstance = EncodingInstance;
  91.            
  92.             // If we shall connect immediately...
  93.             if (ConnectImmediately)
  94.             {
  95.                 try
  96.                 {
  97.                     // Create a socket which connects immediately
  98.                     _Socket = new System.Net.Sockets.TcpClient(IPAdress, Port);
  99.                     _Connected = _Socket.Connected;
  100.                 }
  101.                 catch (Exception)
  102.                 {
  103.  
  104.                 }
  105.             }
  106.             else
  107.             {
  108.                 // Else, initialize a new, not connecting socket
  109.                 _Socket = new System.Net.Sockets.TcpClient();
  110.                 _IPAdress = IPAdress;
  111.                 _Port = Port;
  112.             }           
  113.         }
  114.         #endregion
  115.  
  116.         #region Private Methods
  117.         /// <summary>
  118.         /// Worker Function for client listening
  119.         /// </summary>
  120.         private void _ClientThreadFunc()
  121.         {
  122.             // Enter listening loop
  123.             while (true)
  124.             {
  125.                 // Give the other threads 1 miliseconds to do their work, else a 100% CPU load is guaranteed.
  126.                 System.Threading.Thread.Sleep(1);
  127.  
  128.                 // Message Bytes
  129.                 Byte[] data = new Byte[_BufferLength];
  130.  
  131.                 // String to store the response ASCII representation.
  132.                 string responseData = string.Empty;
  133.  
  134.                 // Read the first batch of the TcpServer response bytes.
  135.                 Int32 bytes = _Stream.Read(data, 0, data.Length);
  136.  
  137.                 // Placeholder for writing in the recieved data.
  138.                 responseData = _EncodingInstance.GetString(data, 0, bytes);
  139.  
  140.                 // Call MessageReceived event, if it has event handlers
  141.                 if (MessageRecieved != null)
  142.                 {
  143.                     MessageRecieved(this, responseData);
  144.                 }
  145.             }
  146.         }
  147.         #endregion
  148.  
  149.         #region Public Methods
  150.         /// <summary>
  151.         /// Sends a message to the Server
  152.         /// </summary>
  153.         /// <param name="Message">Message to send</param>
  154.         public void SendMessage(string Message)
  155.         {
  156.             // Convert string into bytes
  157.             byte[] msg = _EncodingInstance.GetBytes(Message);
  158.  
  159.             // Send the bytes to the stream.
  160.             _Stream.Write(msg, 0, msg.Length);
  161.         }
  162.         /// <summary>
  163.         /// Connect to the endpoint
  164.         /// </summary>
  165.         /// <returns></returns>
  166.         public bool Connect()
  167.         {           
  168.             // If we have an IP
  169.             if (_IPAdress == string.Empty || _Port == 0)
  170.             {
  171.                 // If not, return false
  172.                 return false;
  173.             }
  174.             else
  175.             {
  176.                 // If there was a socket before
  177.                 if (Socket != null)
  178.                 {
  179.                     // and if it was connected, disconnect it
  180.                     if (!_Socket.Connected)
  181.                         _Socket.Close();
  182.                 }
  183.                 else
  184.                 {
  185.                     // else create a new one.
  186.                     _Socket = new System.Net.Sockets.TcpClient();
  187.                 }
  188.  
  189.                 // If everything's fine, connect it.
  190.                 _Socket.Connect(_IPAdress, _Port);
  191.                
  192.                 // If the socket is connected
  193.                 if (_Socket.Connected)
  194.                 {
  195.                     // Retrieve a stream
  196.                     _Stream = _Socket.GetStream();
  197.  
  198.                     // And start the listening thread
  199.                     _ClientThread = new System.Threading.Thread(new System.Threading.ThreadStart(_ClientThreadFunc));
  200.                     _ClientThread.Start();                   
  201.                 }
  202.  
  203.                 // Last but not least, return success or fail message
  204.                 return _Socket.Connected;
  205.             }
  206.         }       
  207.         #endregion
  208.  
  209.         #region Events
  210.         /// <summary>
  211.         /// Called when the client received a message
  212.         /// </summary>
  213.         /// <param name="sender">This ServerClient</param>
  214.         /// <param name="Message">Received message</param>
  215.         public delegate void MessageRecievedDelegate(object sender, string Message);
  216.  
  217.         /// <summary>
  218.         /// Called when the client received a message
  219.         /// </summary>
  220.         public event MessageRecievedDelegate MessageRecieved;
  221.         #endregion
  222.  
  223.     }
  224. }
Server.cs
Code
  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2. *  Copyright (C) Marco Klein alias WorldRacer, WorldRacer92, WorldRacer_original  *
  3. *                                                                                 *
  4. *   This program is free software: you can redistribute it and/or modify          *
  5. *   it under the terms of the GNU General Public License as published by          *
  6. *   the Free Software Foundation, either version 3 of the License, or             *
  7. *   (at your option) any later version.                                           *
  8. *                                                                                 *
  9. *   This program is distributed in the hope that it will be useful,               *
  10. *   but WITHOUT ANY WARRANTY; without even the implied warranty of                *
  11. *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
  12. *   GNU General Public License for more details.                                  *
  13. *                                                                                 *
  14. *   You should have received a copy of the GNU General Public License             *
  15. *   along with this program.  If not, see <http://www.gnu.org/licenses/>.         *
  16. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  17.  
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Linq;
  21. using System.Text;
  22.  
  23. namespace devNetworks
  24. {
  25.     /// <summary>
  26.     /// This class represents a multi-client server
  27.     /// </summary>
  28.     public class Server
  29.     {
  30.         #region Public Attributes
  31.         /// <summary>
  32.         /// Socket. (TcpClient)
  33.         /// </summary>
  34.         public System.Net.Sockets.TcpListener Socket
  35.         {
  36.             get { return _Listener; }
  37.             set { _Listener = value; }
  38.         }
  39.         #endregion
  40.  
  41.         #region Private Attributes
  42.         // Listener.
  43.         private System.Net.Sockets.TcpListener _Listener = null;
  44.  
  45.         // List of connected clients.
  46.         private List<ServerClient> _ConnectedClients = new List<ServerClient>();
  47.  
  48.         // Bufferlength
  49.         int _BufferLength = 4096;
  50.  
  51.         // Get a client stream for reading and writing.       
  52.         System.Net.Sockets.NetworkStream _Stream;
  53.  
  54.         // How shall the messages be encoded to?
  55.         System.Text.Encoding _EncodingInstance = System.Text.Encoding.ASCII;
  56.        
  57.         // Thread for handling server Messages
  58.         System.Threading.Thread _ListenThread = null;
  59.  
  60.         #endregion
  61.  
  62.         #region Constructor
  63.         /// <summary>
  64.         /// Initializes a new Multiple-Connection-Server
  65.         /// </summary>
  66.         /// <param name="Port">Port to listen on</param>
  67.         /// <param name="LocalEndPoint">IPAdress to bind</param>
  68.         /// <param name="EncodingInstance">How shall the messages be encoded to?</param>
  69.         public Server(int Port, System.Net.IPAddress LocalEndPoint, Encoding EncodingInstance)
  70.         {
  71.             _EncodingInstance = EncodingInstance;
  72.             _Listener = new System.Net.Sockets.TcpListener(LocalEndPoint, Port);
  73.         }       
  74.         #endregion
  75.  
  76.         #region Private Methods
  77.         /// <summary>
  78.         /// Thread to handle a client
  79.         /// </summary>
  80.         /// <param name="ClientObject">TcpClient. Client to handle</param>
  81.         private void _AddClient(object ClientObject)
  82.         {
  83.             // Perform a blocking call to accept requests.
  84.             // You could also user server.AcceptSocket() here.               
  85.             ServerClient Client = new ServerClient(((System.Net.Sockets.TcpClient)ClientObject), this._EncodingInstance);
  86.             Client.MessageRecieved += new ServerClient.MessageRecievedDelegate(_Client_MessageRecieved);
  87.             _ConnectedClients.Add(Client);
  88.             ClientConnected(this, _ConnectedClients[_ConnectedClients.Count - 1]);           
  89.         }
  90.  
  91.         /// <summary>
  92.         /// Overridable function, for child classes. Here you can define what to do with recieved messages
  93.         /// </summary>
  94.         /// <param name="sender">The Server class</param>
  95.         /// <param name="Message">Received Message</param>
  96.         protected virtual void _Client_MessageRecieved(object sender, string Message)
  97.         {
  98.            
  99.         }
  100.         /// <summary>
  101.         /// Worker function for the listening thread
  102.         /// </summary>
  103.         private void _ListenFunc()
  104.         {
  105.             // Give the other threads 1 miliseconds to do their work, else a 100% CPU load is guaranteed.
  106.             System.Threading.Thread.Sleep(1);
  107.  
  108.             // Start listening
  109.             _Listener.Start();
  110.  
  111.             // Buffer for reading data
  112.             Byte[] bytes = new Byte[256];
  113.            
  114.             // Enter the listening loop
  115.             while (true)
  116.             {
  117.                 // Give the other threads 1 miliseconds to do their work, else a 100% CPU load is guaranteed.
  118.                 System.Threading.Thread.Sleep(1);
  119.  
  120.                 // Start a new thread to handle the client in a asynchronous whay
  121.                 (new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(_AddClient))).Start(_Listener.AcceptTcpClient());
  122.             }
  123.         }
  124.         #endregion
  125.  
  126.         #region Public Methods
  127.         /// <summary>
  128.         /// Start Listening for Clients
  129.         /// </summary>
  130.         public void StartListening()
  131.         {
  132.             // If there was already a listening thread...
  133.             if (_ListenThread != null)
  134.             {
  135.                 // ...check if listening thread is running. If so, abort it.
  136.                 if (_ListenThread.ThreadState == System.Threading.ThreadState.Running)
  137.                     _ListenThread.Abort();
  138.             }
  139.  
  140.             // Create a new listening thread
  141.             _ListenThread = new System.Threading.Thread(new System.Threading.ThreadStart(_ListenFunc));           
  142.         }
  143.  
  144.         public void StopListening()
  145.         {
  146.             // If there was already a listening thread...
  147.             if (_ListenThread != null)
  148.             {
  149.                 // ...check if listening thread is running. If so, abort it.
  150.                 if (_ListenThread.ThreadState == System.Threading.ThreadState.Running)
  151.                     _ListenThread.Abort();
  152.             }
  153.         }
  154.         #endregion
  155.  
  156.         #region Events
  157.         /// <summary>
  158.         /// Called when a client has connected
  159.         /// </summary>
  160.         /// <param name="sender">The devNetworks.Server object</param>
  161.         /// <param name="Client"></param>
  162.         public delegate void ClientConnectedDelegate(object sender, ServerClient Client);
  163.  
  164.         /// <summary>
  165.         /// Called when a client has connected
  166.         /// </summary>
  167.         public event ClientConnectedDelegate ClientConnected;
  168.         #endregion
  169.     }
  170. }
ServerClient.cs
Code
  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2. *  Copyright (C) Marco Klein alias WorldRacer, WorldRacer92, WorldRacer_original  *
  3. *                                                                                 *
  4. *   This program is free software: you can redistribute it and/or modify          *
  5. *   it under the terms of the GNU General Public License as published by          *
  6. *   the Free Software Foundation, either version 3 of the License, or             *
  7. *   (at your option) any later version.                                           *
  8. *                                                                                 *
  9. *   This program is distributed in the hope that it will be useful,               *
  10. *   but WITHOUT ANY WARRANTY; without even the implied warranty of                *
  11. *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
  12. *   GNU General Public License for more details.                                  *
  13. *                                                                                 *
  14. *   You should have received a copy of the GNU General Public License             *
  15. *   along with this program.  If not, see <http://www.gnu.org/licenses/>.         *
  16. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  17.  
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Linq;
  21. using System.Text;
  22.  
  23. namespace devNetworks
  24. {
  25.     /// <summary>
  26.     /// This class represents a client which has connected to a devNetworks.Server
  27.     /// </summary>
  28.     public class ServerClient
  29.     {
  30.         #region Public Attributes
  31.         /// <summary>
  32.         /// Socket. (TcpClient)
  33.         /// </summary>
  34.         public System.Net.Sockets.TcpClient Socket
  35.         {
  36.             get { return _Socket; }
  37.             set { _Socket = value; }
  38.         }
  39.         #endregion
  40.  
  41.         #region Private Attributes
  42.         // Socket to handle with
  43.         private System.Net.Sockets.TcpClient _Socket = null;
  44.  
  45.         // Thread for handling server Messages
  46.         System.Threading.Thread _ClientThread = null;
  47.  
  48.         // IP-Adress of the endpoint
  49.         private string _IPAdress = string.Empty;
  50.  
  51.         // Port to connect at the entpoint
  52.         private int _Port = 0;
  53.  
  54.         // Contains whether we are connected or not.
  55.         private bool _Connected = false;
  56.  
  57.         // Bufferlength
  58.         int _BufferLength = 4096;
  59.  
  60.         // Get a client stream for reading and writing.
  61.         //  Stream stream = client.GetStream();
  62.         System.Net.Sockets.NetworkStream _Stream;
  63.  
  64.         // How shall the messages be encoded to?
  65.         System.Text.Encoding _EncodingInstance = System.Text.Encoding.ASCII;
  66.         #endregion
  67.  
  68.         #region Constructor
  69.         /// <summary>
  70.         /// Initializes a client connected to a devNetworks.Server
  71.         /// </summary>
  72.         /// <param name="Socket">TcpClient</param>
  73.         /// <param name="EncodingInstance">How shall the messages be encoded to?</param>
  74.         public ServerClient(System.Net.Sockets.TcpClient Socket, Encoding EncodingInstance)
  75.         {
  76.             // Save the values
  77.             _EncodingInstance = EncodingInstance;
  78.             _Socket = Socket;
  79.            
  80.             // Retrieve a stream
  81.             _Stream = _Socket.GetStream();
  82.  
  83.             // Start a listening stream to listen on clients messages
  84.             _ClientThread = new System.Threading.Thread(new System.Threading.ThreadStart(_ClientThreadFunc));
  85.             _ClientThread.Start();
  86.         }       
  87.         #endregion
  88.  
  89.         #region Private Methods
  90.         /// <summary>
  91.         /// Worker Function for client listening
  92.         /// </summary>
  93.         private void _ClientThreadFunc()
  94.         {
  95.             // Enter listening loop
  96.             while (true)
  97.             {
  98.                 // Give the other threads 1 miliseconds to do their work, else a 100% CPU load is guaranteed.
  99.                 System.Threading.Thread.Sleep(1);
  100.  
  101.                 // Message Bytes
  102.                 Byte[] data = new Byte[_BufferLength];
  103.  
  104.                 // String to store the response ASCII representation.
  105.                 string responseData = string.Empty;
  106.  
  107.                 // Read the first batch of the TcpServer response bytes.
  108.                 Int32 bytes = _Stream.Read(data, 0, data.Length);
  109.  
  110.                 // Placeholder for writing in the recieved data.
  111.                 responseData = _EncodingInstance.GetString(data, 0, bytes);
  112.  
  113.                 // Call MessageReceived event, if it has event handlers
  114.                 if (MessageRecieved != null)
  115.                 {
  116.                     MessageRecieved(this, responseData);
  117.                 }
  118.             }
  119.         }
  120.         #endregion
  121.  
  122.         #region Public Methods
  123.         /// <summary>
  124.         /// Sends a message to the Client
  125.         /// </summary>
  126.         /// <param name="Message">Message to send</param>
  127.         public void SendMessage(string Message)
  128.         {
  129.             // Convert string into bytes
  130.             byte[] msg = _EncodingInstance.GetBytes(Message);
  131.  
  132.             // Send the bytes to the stream.
  133.             _Stream.Write(msg, 0, msg.Length);
  134.         }
  135.         #endregion
  136.  
  137.         #region Events
  138.         /// <summary>
  139.         /// Called when the server received a message
  140.         /// </summary>
  141.         /// <param name="sender">This ServerClient</param>
  142.         /// <param name="Message">Received message</param>
  143.         public delegate void MessageRecievedDelegate(object sender, string Message);
  144.  
  145.         /// <summary>
  146.         /// Called when the server received a message
  147.         /// </summary>
  148.         public event MessageRecievedDelegate MessageRecieved;
  149.         #endregion
  150.     }
  151. }


Gruesse, WorldRacer

"Was man bekommt, wenn man etwas nicht bekommt, ist Erfahrung"

INFO:
Mein Rechner wie er leibt und lebt |
Technischen Post korrekt verfassen (Wir haben keine Glaskugel!) *g*