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; } } }
浙公网安备 33010602011771号