TCP - C# - 服务器客户端聊天比较

时间:2014-03-19 09:45:24

标签: c# sockets tcp client-server

我设法创建了一个服务器/客户端聊天系统,客户端向服务器发送消息,服务器将消息发送给所有客户端。

我想对此进行扩展,以便服务器比较消息,然后向客户端发送消息。

例如:如果客户端1发送10而客户端2发送20,则服务器将比较这些,服务器将发送一条消息,表示20超过10。

这可能吗?如果是这样的话?

服务器代码:

namespace Server
{
    public partial class Form1 : Form
    {

        private const int m_iMaxConnections = 2;

        struct Connection_Struct    // Define a structure to hold details about a single connection
        {
            public Socket ClientSpecific_Socket;
            public bool bInUse;
        };

        Socket m_ListenSocket;
        Socket m_SendSocket;

        Connection_Struct[] m_Connection_Array = new Connection_Struct[m_iMaxConnections]; // Define an array to hold a number of connections

        System.Net.IPEndPoint m_LocalIPEndPoint;
        static int m_iNumberOfConnectedClients;
        private static System.Windows.Forms.Timer m_CommunicationActivity_Timer;

        public Form1()
        {
            InitializeComponent();

            Initialise_ConnectionArray();
            m_CommunicationActivity_Timer = new System.Windows.Forms.Timer(); // Check for communication activity on Non-Blocking sockets every 200ms
            m_CommunicationActivity_Timer.Tick += new EventHandler(OnTimedEvent_PeriodicCommunicationActivityCheck); // Set event handler method for timer
            m_CommunicationActivity_Timer.Interval = 100;  // Timer interval is 1/10 second
            m_CommunicationActivity_Timer.Enabled = false;
            string szLocalIPAddress = GetLocalIPAddress_AsString(); // Get local IP address as a default value
            txtIPAddress.Text = szLocalIPAddress;             // Place local IP address in IP address field
            txtPort.Text = "8000";  // Default port number
            m_iNumberOfConnectedClients = 0;
            txtClientNo.Text = System.Convert.ToString(m_iNumberOfConnectedClients);

            try
            {   // Create the Listen socket, for TCP use
                m_ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_ListenSocket.Blocking = false;
                m_SendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Tcp);
            }
            catch (SocketException se)
            {   // If an exception occurs, display an error message
                MessageBox.Show(se.Message);
            }

        }


        private void Initialise_ConnectionArray()
        {
            int iIndex;
            for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
            {
                m_Connection_Array[iIndex].bInUse = false;
            }
        }



        private void btnEnableServer_Click(object sender, EventArgs e)
        {


            // Bind to the selected port and start listening / receiving
            try
            {
                // Get the Port number from the appropriate text box
                String szPort = txtPort.Text;
                int iPort = System.Convert.ToInt16(szPort, 10);
                // Create an Endpoint that will cause the listening activity to apply to all the local node's interfaces
                m_LocalIPEndPoint = new System.Net.IPEndPoint(IPAddress.Any, iPort);
                // Bind to the local IP Address and selected port
                m_ListenSocket.Bind(m_LocalIPEndPoint);

                txtLog.Text = "Bind succeded";

                // Prevent any further changes to the port number
                txtPort.ReadOnly = true;
            }

            catch // Catch any errors
            {   // If an exception occurs, display an error message
                txtLog.Text = "Bind failed";
            }





            try
            {
                txtLog.Text = "Listening";
                m_ListenSocket.Listen(2); // Listen for connections, with a backlog / queue maximum of 2

            }
            catch (SocketException se)
            {
                // If an exception occurs, display an error message
                MessageBox.Show(se.Message);
            }
            catch // Silently handle any other exception
            {
            }



            m_CommunicationActivity_Timer.Start();  // Start the timer to perform periodic checking for connection requests   
            txtLog.Text = "Accepting (waiting for connection attempt)";
            btnEnableServer.Enabled = false;



        }




        private void OnTimedEvent_PeriodicCommunicationActivityCheck(Object myObject, EventArgs myEventArgs)
        {   // Periodic check whether a connection request is pending or a message has been received on a connected socket     

            // First, check for pending connection requests
            int iIndex;
            iIndex = GetnextAvailable_ConnectionArray_Entry(); // Find an available array entry for next connection request
            if (-1 != iIndex)
            {   // Only continue with Accept if there is an array entry available to hold the details

                try
                {
                    m_Connection_Array[iIndex].ClientSpecific_Socket = m_ListenSocket.Accept();  // Accept a connection (if pending) and assign a new socket to it (AcceptSocket)
                    // Will 'catch' if NO connection was pending, so statements below only occur when a connection WAS pending
                    m_Connection_Array[iIndex].bInUse = true;
                    m_Connection_Array[iIndex].ClientSpecific_Socket.Blocking = false;           // Make the new socket operate in non-blocking mode
                    m_iNumberOfConnectedClients++;
                    txtClientNo.Text = System.Convert.ToString(m_iNumberOfConnectedClients);
                    txtLog.Text = "A new client connected";

                    SendUpdateMesageToAllConnectedclients();
                }
                catch (SocketException se) // Handle socket-related exception
                {   // If an exception occurs, display an error message
                    if (10053 == se.ErrorCode || 10054 == se.ErrorCode) // Remote end closed the connection
                    {
                        CloseConnection(iIndex);
                    }
                    else if (10035 != se.ErrorCode)
                    {   // Ignore error messages relating to normal behaviour of non-blocking sockets
                        MessageBox.Show(se.Message);
                    }
                }
                catch // Silently handle any other exception
                {
                }
            }

            // Second, check for received messages on each connected socket
            for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
            {
                if (true == m_Connection_Array[iIndex].bInUse)
                {
                    try
                    {
                        EndPoint localEndPoint = (EndPoint)m_LocalIPEndPoint;
                        byte[] ReceiveBuffer = new byte[1024];
                        int iReceiveByteCount;
                        iReceiveByteCount = m_Connection_Array[iIndex].ClientSpecific_Socket.ReceiveFrom(ReceiveBuffer, ref localEndPoint);

                        string szReceivedMessage;
                        if (0 < iReceiveByteCount)
                        {   // Copy the number of bytes received, from the message buffer to the text control
                            szReceivedMessage = Encoding.ASCII.GetString(ReceiveBuffer, 0, iReceiveByteCount);
                            if ("QuitConnection" == szReceivedMessage)
                            {
                                CloseConnection(iIndex);
                            }
                            else
                            {

                               txtLog.AppendText(szReceivedMessage + Environment.NewLine);


                                // Send message to each connected client.

                                //  int iIndex2;
                                for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
                                {
                                    if (true == m_Connection_Array[iIndex].bInUse)
                                    {
                                        string szMessage;

                                        szMessage = szReceivedMessage;

                                        txtLog.Text = m_Connection_Array[m_iMaxConnections].ToString();



                                        byte[] SendMessage = System.Text.Encoding.ASCII.GetBytes(szMessage);
                                        m_Connection_Array[iIndex].ClientSpecific_Socket.Send(SendMessage, SocketFlags.None);
                                    }
                                }



                            }
                        }
                    }
                    catch (SocketException se) // Handle socket-related exception
                    {   // If an exception occurs, display an error message
                        if (10053 == se.ErrorCode || 10054 == se.ErrorCode) // Remote end closed the connection
                        {
                            CloseConnection(iIndex);
                        }
                        else if (10035 != se.ErrorCode)
                        {   // Ignore error messages relating to normal behaviour of non-blocking sockets
                            MessageBox.Show(se.Message);
                        }
                    }
                    catch // Silently handle any other exception
                    {
                    }
                }
            }
        }





        private void SendUpdateMesageToAllConnectedclients()
        {   // Send message to each connected client informing of the total number of connected clients
            int iIndex;
            for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
            {
                if (true == m_Connection_Array[iIndex].bInUse)
                {
                    string szMessage;
                    if (1 == m_iNumberOfConnectedClients)
                    {
                        szMessage = string.Format("There is now {0} client connected", m_iNumberOfConnectedClients);
                    }
                    else
                    {
                        szMessage = string.Format("There are now {0} clients connected", m_iNumberOfConnectedClients);
                    }
                    byte[] SendMessage = System.Text.Encoding.ASCII.GetBytes(szMessage);
                    m_Connection_Array[iIndex].ClientSpecific_Socket.Send(SendMessage, SocketFlags.None);
                }
            }
        }

        private void CloseConnection(int iIndex)
        {
            try
            {
                m_Connection_Array[iIndex].bInUse = false;
                m_Connection_Array[iIndex].ClientSpecific_Socket.Shutdown(SocketShutdown.Both);
                m_Connection_Array[iIndex].ClientSpecific_Socket.Close();
                m_iNumberOfConnectedClients--;
                txtClientNo.Text = System.Convert.ToString(m_iNumberOfConnectedClients);
                txtLog.Text = "A Connection was closed";
                SendUpdateMesageToAllConnectedclients();
            }
            catch // Silently handle any exceptions
            {
            }
        }





        private void Close_And_Quit()
        {   // Close the sockets and exit the application
            try
            {
                m_ListenSocket.Close();
            }
            catch
            {
            }
            try
            {
                int iIndex;
                for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
                {
                    m_Connection_Array[iIndex].ClientSpecific_Socket.Shutdown(SocketShutdown.Both);
                    m_Connection_Array[iIndex].ClientSpecific_Socket.Close();
                }
            }
            catch
            {
            }
            try
            {
                Close();
            }
            catch
            {
            }
        }



        public string GetLocalIPAddress_AsString()
        {
            string szHost = Dns.GetHostName();
            string szLocalIPaddress = "127.0.0.1";  // Default is local loopback address
            IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress IP in IPHost.AddressList)
            {
                if (IP.AddressFamily == AddressFamily.InterNetwork) // Match only the IPv4 address
                {
                    szLocalIPaddress = IP.ToString();
                    break;
                }
            }
            return szLocalIPaddress;
        }


        private int GetnextAvailable_ConnectionArray_Entry()
        {
            int iIndex;
            for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
            {
                if (false == m_Connection_Array[iIndex].bInUse)
                {
                    return iIndex;  // Return the index value of the first not-in-use entry found
                }
            }
            return -1;      // Signal that there were no available entries
        }



    }
}

客户代码:

namespace Client
{
public partial class Form1 : Form
{

    Socket m_ClientSocket;
    System.Net.IPEndPoint m_remoteEndPoint;
    IPEndPoint m_localIPEndPoint;
    Socket m_ReceiveSocket;

    private static System.Windows.Forms.Timer m_CommunicationActivity_Timer;

    public Form1()
    {
        InitializeComponent();

        m_CommunicationActivity_Timer = new System.Windows.Forms.Timer(); // Check for communication activity on Non-Blocking sockets every 200ms
        m_CommunicationActivity_Timer.Tick += new EventHandler(OnTimedEvent_PeriodicCommunicationActivityCheck); // Set event handler method for timer
        m_CommunicationActivity_Timer.Interval = 100;  // Timer interval is 1/10 second
        m_CommunicationActivity_Timer.Enabled = false;

        string szLocalIPAddress = GetLocalIPAddress_AsString(); // Get local IP address as a default value
        txtIPAddress.Text = szLocalIPAddress;             // Place local IP address in IP address field
        txtPort.Text = "8000"; // Default port number


    }

    private void btnConnect_Click(object sender, EventArgs e)
    {



        // Connect the Socket with a remote endpoint
        try
        {
            // Create the socket, for TCP use
            m_ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            m_ClientSocket.Blocking = true; // Socket operates in Blocking mode initially
        }
        catch // Handle any exceptions
        {
            Close_Socket_and_Exit();
        }
        try
        {
            // Get the IP address from the appropriate text box
            String szIPAddress = txtIPAddress.Text;
            System.Net.IPAddress DestinationIPAddress = System.Net.IPAddress.Parse(szIPAddress);

            // Get the Port number from the appropriate text box
            String szPort = txtPort.Text;
            int iPort = System.Convert.ToInt16(szPort, 10);

            // Combine Address and Port to create an Endpoint
            m_remoteEndPoint = new System.Net.IPEndPoint(DestinationIPAddress, iPort);

            m_ClientSocket.Connect(m_remoteEndPoint);
            m_ClientSocket.Blocking = false;    // Socket is now switched to Non-Blocking mode for send/ receive activities
            txtLog.Text = "Connected";


            m_CommunicationActivity_Timer.Start();  // Start the timer to perform periodic checking for received messages   
        }
        catch // Catch all exceptions
        {   // If an exception occurs, display an error message
            txtLog.Text = "(Connect attempt failed)\nRetry Connect";
        }







    }



    private void OnTimedEvent_PeriodicCommunicationActivityCheck(Object myObject, EventArgs myEventArgs)
    {   // Periodic check whether a message has been received    
        try
        {
            EndPoint RemoteEndPoint = (EndPoint)m_remoteEndPoint;
            byte[] ReceiveBuffer = new byte[1024];
            int iReceiveByteCount;
            iReceiveByteCount = m_ClientSocket.ReceiveFrom(ReceiveBuffer, ref RemoteEndPoint);

            string szReceivedMessage;
            if (0 < iReceiveByteCount)
            {   // Copy the number of bytes received, from the message buffer to the text control
                szReceivedMessage = Encoding.ASCII.GetString(ReceiveBuffer, 0, iReceiveByteCount);

               txtResult.Text = szReceivedMessage;
            }
        }
        catch // Silently handle any exceptions
        {
        }
    }

    private void Close_Socket_and_Exit()
    {
        try
        {
            m_ClientSocket.Shutdown(SocketShutdown.Both);
        }
        catch // Silently handle any exceptions
        {
        }
        try
        {
            m_ClientSocket.Close();
        }
        catch // Silently handle any exceptions
        {
        }
        this.Close();
    }

    private void btnDisconnect_Click(object sender, EventArgs e)
    {


        try
        {
            String szData = "QuitConnection"; // Special code to signal 'close connection' to the server
            // This ensures that the server is aware the Client wants to close the connection
            // (TCP should otherwise automatically detect disconnection, but this approach ensures a clean disconnect)
            byte[] byData = System.Text.Encoding.ASCII.GetBytes(szData);
            m_ClientSocket.Send(byData, SocketFlags.None);
            m_ClientSocket.Shutdown(SocketShutdown.Both);
            m_ClientSocket.Close();


            btnConnect.Text = "Connect";
            txtResult.Text = "";

        }
        catch // Silently handle any exceptions
        {
        }






    }



    private string GetLocalIPAddress_AsString()
    {
        string szHost = Dns.GetHostName();
        string szLocalIPaddress = "127.0.0.1";  // Default is local loopback address
        IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
        foreach (IPAddress IP in IPHost.AddressList)
        {
            if (IP.AddressFamily == AddressFamily.InterNetwork) // Match only the IPv4 address
            {
                szLocalIPaddress = IP.ToString();
                break;
            }
        } return szLocalIPaddress;
    }

}
}

0 个答案:

没有答案