网络设计与技术
吾爱吾师但吾更爱真理,尽信书不如无书!科学的原动力就是对权威的藐视和对新思想的宽容!

  教育是帮助学生学会自己思考,作出独立的判断,并作为一个负责的公民参加工作!仰不愧天,俯不愧人,内不愧心!

  主要介绍网络原理、网络数据库、网络编程、网站设计
  网络操作系统(Windows Server & Linux)、网络管理、和网络安全(协议 & 黑客攻防)等技术。

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;


namespace IMServerbyTCPinLAN
{
    public partial class Form1 : Form
    {
        internal static Hashtable clients = new Hashtable();
        private TcpListener listener;
        static int MAX_NUM = 100;
        internal static bool ServiceFlag = false;

        public Form1()
        {
            InitializeComponent();
            txtPort.Text = "9988";
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            int port = getValidPort(txtPort.Text);
            if (port < 0)
                return;

            string ip = getIPAddress();
            try
            {
                IPAddress ipAdd = IPAddress.Parse(ip);
                listener = new TcpListener(ipAdd, port);
                listener.Start();
                tbMsg.AppendText("服务器已经启动,正在监听 " + ip + ", 端口号:" + txtPort.Text + Environment.NewLine);

                //启动一个新的线程,执行方法StartListen,
                //以便在一个独立的进程中执行确认与客户端Socket连接的操作
                ServiceFlag = true;
                Thread thread = new Thread(new ThreadStart(StartListen));
                thread.Start();
                btnStart.Enabled = false;
                btnEnd.Enabled = true;
            }
            catch (Exception ex)
            {
                tbMsg.AppendText(ex.Message.ToString() + "\r\n");
            }
        }

        private void btnEnd_Click(object sender, EventArgs e)
        {
            tbMsg.AppendText("服务器已经停止监听. \r\n");
            ServiceFlag = false;
            btnStart.Enabled = true;
            btnEnd.Enabled = false;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            ServiceFlag = false;
        }

        private string getIPAddress()
        {
            //获得本机局域网IP地址
            IPAddress ip = null;
            IPAddress[] AddressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
            if (AddressList.Length < 1)
                return "";
            for (int i = 0; i < AddressList.Length; i++)
                if (AddressList[i].AddressFamily == AddressFamily.InterNetwork)     // 获取 IPv4 地址
                {
                    ip = AddressList[i];
                    break;
                }
            return ip.ToString();
        }

        private int getValidPort(string port)
        {
            int lport;
            try
            {
                if (port == "")
                    throw new ArgumentException("端口号为空,不能启动服务器具");
                lport = System.Convert.ToInt32(port);
            }
            catch (Exception e)
            {
                Console.WriteLine("无效的端口号:" + e.ToString());
                tbMsg.AppendText("无效的端口号:" + e.ToString() + "\r\n");
                return -1;
            }
            return lport;
        }

        delegate void AddMagCallback(string text);
        private void AddMsg(string text)
        {
            if (tbMsg.InvokeRequired)
            {
                while (!tbMsg.IsHandleCreated)
                    //解决窗体关闭时出现“访问已释放句柄“的异常
                    if (tbMsg.Disposing || tbMsg.IsDisposed)
                        return;
                AddMagCallback d = new AddMagCallback(AddMsg);
                tbMsg.Invoke(d, new object[] { text });
            }
            else
                tbMsg.AppendText(text);
        }

        delegate void ChangegrpUserCallback(string text);
        private void ChangegrpUser(string text)
        {
            if (grpUser.InvokeRequired)
            {
                while (!grpUser.IsHandleCreated)
                    //解决窗体关闭时出现“访问已释放句柄“的异常
                    if (grpUser.Disposing || grpUser.IsDisposed)
                        return;
                ChangegrpUserCallback d = new ChangegrpUserCallback(ChangegrpUser);
                grpUser.Invoke(d, new object[] { text });
            }
            else
                grpUser.Text = text;
        }

        delegate void AddPersonCallback(string text);
        private void AddPerson(string text)
        {
            if (lstPerson.InvokeRequired)
            {
                while (!lstPerson.IsHandleCreated)
                    //解决窗体关闭时出现“访问已释放句柄“的异常
                    if (lstPerson.Disposing || lstPerson.IsDisposed)
                        return;
                AddPersonCallback d = new AddPersonCallback(AddPerson);
                lstPerson.Invoke(d, new object[] { text });
            }
            else
                lstPerson.Items.Add(text);
        }

        delegate void RemovePersonCallback(string text);
        private void RemovePerson(string text)
        {
            if (lstPerson.InvokeRequired)
            {
                while (!lstPerson.IsHandleCreated)
                    //解决窗体关闭时出现“访问已释放句柄“的异常
                    if (lstPerson.Disposing || lstPerson.IsDisposed)
                        return;
                RemovePersonCallback d = new RemovePersonCallback(RemovePerson);
                lstPerson.Invoke(d, new object[] { text });
            }
            else
                lstPerson.Items.Remove(text);
        }

        public void addUser(string username)
        {
            AddMsg(username + " 进入聊天室\r\n");
            AddPerson(username);
            ChangegrpUser(System.Convert.ToString(clients.Count) + "名在线用户");
        }

        public void removeUser(string username)
        {
            AddMsg(username + " 离开聊天室\r\n");
            RemovePerson(username);
            ChangegrpUser(System.Convert.ToString(clients.Count) + "名在线用户");
        }

        public string GetUserList()
        {
            string Rtn = "";
            for (int i = 0; i < lstPerson.Items.Count; i++)
                Rtn = Rtn + lstPerson.Items[i].ToString() + "|";
            return Rtn;
        }

        public void updateUI(string msg)
        {
            AddMsg(msg + Environment.NewLine);
        }

        //在新的线程中的操作,它主要用于当接收到一个客户端请求时,确认与客户端的连接,
        //并且立刻启动一个新的线程来处理和该客户端的信息交流
        private void StartListen()
        {
            while (ServiceFlag)
            {
                try
                {
                    if (listener.Pending())
                    {
                        Socket socket = listener.AcceptSocket();
                        if (clients.Count > MAX_NUM)
                        {
                            AddMsg("已经达到了最大连接数:" + MAX_NUM + ", 拒绝新的连接\r\n");
                            socket.Close();
                        }
                        else
                        {
                            //启动一个新的线程
                            //执行方法this.ServiceClient,处理用户相应的请求
                            Client client = new Client(this, socket);
                            Thread clientService = new Thread(new ThreadStart(client.ServiceClient));
                            clientService.Start();
                        }
                    }
                    Thread.Sleep(200);
                }
                catch (Exception ex)
                {
                    AddMsg(ex.Message.ToString() + Environment.NewLine);
                }
            }
        }

        public class Client
        {
            private string name;
            private Socket currentSocket = null;
            private string ipAddress;
            private Form1 server;

            AesCryptoServiceProvider myAes;

            private string state = "closed";

            public Client(Form1 server, Socket clientSocket)
            {
                this.server = server;
                currentSocket = clientSocket;
                ipAddress = getRemoteIPAddress();

                // Create a new instance of the AesCryptoServiceProvider class.
                try
                {
                    myAes = new AesCryptoServiceProvider();
                    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                    SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider();

                    myAes.Key = sha256.ComputeHash(Encoding.UTF8.GetBytes("Copyright(R) xiesir@gmail.com, 2015-2018, ;-)"));
                    myAes.IV = md5.ComputeHash(Encoding.UTF8.GetBytes("Copyright 2015-2018"));
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error: {0}", e.Message);
                }
            }

            public string Name
            {
                get
                {
                    return name;
                }
                set
                {
                    name = value;
                }
            }

            public Socket CurrrentSocket
            {
                get
                {
                    return currentSocket;
                }
                set
                {
                    currentSocket = value;
                }
            }

            public string IpAddress
            {
                get
                {
                    return ipAddress;
                }
            }

            private string getRemoteIPAddress()
            {
                return ((IPEndPoint) currentSocket.RemoteEndPoint).Address.ToString();
            }

            private void SendToClient(Client client, string msg)
            {
                // Non-Encrypt
                Byte[] message = Encoding.Default.GetBytes(msg.ToCharArray());

                // Aes Encrypt
                //byte[] message = EncryptStringToBytes_Aes(msg, myAes.Key, myAes.IV);
                client.CurrrentSocket.Send(message, message.Length, 0);
            }

            //ServiceClient方法用于和客户端进行数据通信,包括接收客户端的请求,
            //它根据不同的请求命令执行相应的操作,并将处理结果返回到客户端
            public void ServiceClient()
            {
                string[] tokens = null;
                byte[] buff = new byte[1024];
                bool keepConnect = true;
                //用循环来不断地与客户端进行交互,直到客户端发出“EXIT”命令,
                //将keepConnect置为false,退出循环,关闭连接,并中止当前线程
                while (keepConnect && Form1.ServiceFlag)
                {
                    tokens = null;
                    try
                    {
                        if (currentSocket == null || currentSocket.Available < 1)
                        {
                            Thread.Sleep(300);
                            continue;
                        }
                        int len = currentSocket.Receive(buff);
                        // AES Decrypt
                        //string clientCommand = DecryptStringFromBytes_Aes(buff, myAes.Key, myAes.IV);

                        // Non-Decrypt
                        string clientCommand = Encoding.Default.GetString(buff, 0, len);

                        tokens = clientCommand.Split(new char[] { '|' });
                        if (tokens == null)
                        {
                            Thread.Sleep(200);
                            continue;
                        }
                    }
                    catch (Exception e)
                    {
                        server.updateUI("发生异常:" + e.ToString());
                    }
                    if (tokens[0] == "CONN")
                    {
                        name = tokens[1];
                        if (Form1.clients.Contains(this.name))
                        {
                            SendToClient(this, "ERR|User " + this.name + " 已经存在");
                        }
                        else
                        {
                            Hashtable syncClients = Hashtable.Synchronized(Form1.clients);
                            syncClients.Add(this.name, this);

                            server.addUser(this.name);

                            //对每一个当前在线的用户发送JOIN消息命令和LIST消息命令,
                            //以此来更新客户端的当前在线用户列表
                            IEnumerator myEnumerator = Form1.clients.Values.GetEnumerator();
                            while (myEnumerator.MoveNext())
                            {
                                Client client = (Client)myEnumerator.Current;
                                SendToClient(client, "JOIN|" + tokens[1] + "|");
                                Thread.Sleep(100);
                            }
                            state = "connected";
                            SendToClient(this, "ok");
                            //向客户端发送LIST命令,以此更新客户端的当前在线用户列表
                            string msgUsers = "LIST|" + server.GetUserList();
                            SendToClient(this, msgUsers);
                        }
                    }
                    else if (tokens[0] == "LIST")
                    {
                        if (state == "connected")
                        {
                            //向客户端发送LIST命令,以此更新客户端的当前在线用户列表
                            string msgUsers = "LIST|" + server.GetUserList();
                            SendToClient(this, msgUsers);
                        }
                        else
                        {
                            SendToClient(this, "ERR|state error,Please login first");
                        }
                    }
                    else if (tokens[0] == "CHAT")
                    {
                        if (state == "connected")
                        {
                            string message = string.Empty;
                            IEnumerator myEnumerator = Form1.clients.Values.GetEnumerator();
                            while (myEnumerator.MoveNext())
                            {
                                Client client = (Client) myEnumerator.Current;
                                message = "用户 " + tokens[1].Split(':')[0] + " 对大家说: " + tokens[1].Split(':')[1];
                                SendToClient(client, message);
                            }
                            if (!string.IsNullOrEmpty(message))
                            {
                                server.updateUI(message);
                            }
                        }
                        else
                        {
                            SendToClient(this, "ERR|state error,Please login first");
                        }
                    }
                    else if (tokens[0] == "PRIV")
                    {
                        if (state == "connected")
                        {
                            string sender = tokens[1];
                            string receiver = tokens[2];
                            string content = tokens[3];
                            string message = sender + "" + receiver + " 说: " + content;

                            if (Form1.clients.Contains(sender))
                                SendToClient((Client)Form1.clients[sender], message);
                            if (Form1.clients.Contains(receiver))
                                SendToClient((Client)Form1.clients[receiver], message);
                            server.updateUI(message);
                        }
                        else
                        {
                            SendToClient(this, "ERR|state error Please login first");
                        }
                    }
                    else if (tokens[0] == "EXIT")
                    {
                        if (Form1.clients.Contains(tokens[1]))
                        {
                            Client client = (Client)Form1.clients[tokens[1]];
                            Hashtable syncClients = Hashtable.Synchronized(Form1.clients);
                            syncClients.Remove(client.name);
                            server.removeUser(client.name);
                            //向客户端发送QUIT命令
                            string message = "QUIT|" + tokens[1];
                            IEnumerator myEnumberator = Form1.clients.Values.GetEnumerator();
                            while (myEnumberator.MoveNext())
                            {
                                Client c = (Client)myEnumberator.Current;
                                SendToClient(c, message);
                            }
                            server.updateUI("QUIT");
                        }
                        break;
                    }
                    Thread.Sleep(200);
                }
            }
        }

        static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
        {

            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");
            byte[] encrypted;

            // Create an AesCryptoServiceProvider object with the specified key and IV.
            using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                            swEncrypt.Flush();
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }

            return encrypted;
        }

        static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {

            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold the decrypted text.
            string plaintext = null;

            // Create an AesCryptoServiceProvider object
            // with the specified key and IV.
            using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

            }

            return plaintext;
        }

    }
}

下载

posted on 2015-05-20 09:12  网络设计与技术  阅读(184)  评论(0)    收藏  举报

本站采用CC授权如需转载、引用文章,请务必附上作者及来源处。 Creative Commons License