1. 程式人生 > >C# 簡單通訊(支援一對多)

C# 簡單通訊(支援一對多)

也就伺服器不一樣的寫法,弄了一個類似於Map的容器,其實是字典陣列的感覺,客戶端和原來一樣

服務端:


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

namespace Server2
{
    public partial class Server : Form
    {
        public Server()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }

        Thread threadWatch = null;
        Socket socketWatch = null;

        private void SendServer_Click(object sender, EventArgs e)
        {
            socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            int port = Convert.ToInt32(Port.Text.Trim());
            IPAddress ip = IPAddress.Parse(IP.Text.Trim());
            IPEndPoint ipe = new IPEndPoint(ip, port);
            socketWatch.Bind(ipe);
            socketWatch.Listen(5);
            threadWatch = new Thread(WatchConnect);
            threadWatch.IsBackground = true;
            threadWatch.Start();
            Message.AppendText("伺服器已經啟動,開始監聽..." + "\r\n");
        }

        //感覺和C++的Map一樣的一個容器
        Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();

        Socket socketConnect = null;//與客戶端建立連線的套接字
        string clientName = null;//訪問者的名字
        IPAddress clientIP;//訪問者的IP
        int clientPort;//訪問者的埠號

        private void WatchConnect()
        {
            while (true)
            {
                try
                {
                    socketConnect = socketWatch.Accept();
                }
                catch (Exception ex)
                {
                    Message.AppendText(ex.Message);
                    break;
                }
                clientIP = (socketConnect.RemoteEndPoint as IPEndPoint).Address;//獲取訪問者的IP
                clientPort = (socketConnect.RemoteEndPoint as IPEndPoint).Port;//獲取訪問者的Port
                //建立訪問者的標識,IP + Port
                clientName = "IP:" + clientIP + "Port:" + clientPort;
                ClientList.Items.Add(clientName);//在列表新增訪問者資訊
                dicSocket.Add(clientName,socketConnect);//在字典資料中新增訪問者

                ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRec);
                Thread thread = new Thread(pts);
                thread.IsBackground = true;
                thread.Start(socketConnect);
                Message.AppendText("IP:" + clientIP + " Port:" + clientPort + " 的客戶端與您連線成功,現在你們可以開始通訊了...\r\n");
            }
        }

        string recStr = null;
        private void ServerRec(object obj)
        {
            Socket socketServer = obj as Socket;
            long fileLength = 0;

            while (true)
            {
                int firstRcv = 0;
                byte[] buffer = new byte[8 * 1024];
                try
                {
                    //獲取接受資料的長度,存入記憶體緩衝區,返回一個位元組陣列的長度
                    if (socketServer != null) firstRcv = socketServer.Receive(buffer);

                    if (firstRcv > 0)//大於0,說明有東西傳過來
                    {
                        if (buffer[0] == 0)//0對應文字資訊
                        {
                            recStr = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);
                            Message.AppendText(clientName + ": " + GetTime() + "\r\n" + recStr + "\r\n");
                        }

                        if (buffer[0] == 1)//1對應檔案資訊
                        {
                            string filenameSuffix = recStr.Substring(recStr.LastIndexOf("."));
                            SaveFileDialog sfDialog = new SaveFileDialog()
                            {
                                Filter = "(*" + filenameSuffix + ")|*" + filenameSuffix + "",
                                FileName = recStr
                            };

                            if (sfDialog.ShowDialog(this) == DialogResult.OK)
                            {
                                string savePath = sfDialog.FileName;
                                int rec = 0;
                                long recFileLength = 0;
                                bool firstWrite = true;
                                using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
                                {
                                    while (recFileLength < fileLength)
                                    {
                                        if (firstWrite)
                                        {
                                            fs.Write(buffer, 1, firstRcv - 1);
                                            fs.Flush();
                                            recFileLength += firstRcv - 1;
                                            firstWrite = false;
                                        }
                                        else
                                        {
                                            rec = socketServer.Receive(buffer);
                                            fs.Write(buffer, 0, rec);
                                            fs.Flush();
                                            recFileLength += rec;
                                        }
                                    }
                                    fs.Close();
                                }

                                string fName = savePath.Substring(savePath.LastIndexOf("\\") + 1);
                                string fPath = savePath.Substring(0, savePath.LastIndexOf("\\"));
                                Message.AppendText("你在: " + GetTime() + "\r\n你成功接收 " + clientName + "的檔案" + fName + "\r\n儲存路徑為:" + fPath + "\r\n");
                            }
                        }
                        if (buffer[0] == 2)//2對應檔名字和長度
                        {
                            string fileNameWithLength = Encoding.UTF8.GetString(buffer, 1, firstRcv - 1);
                            recStr = fileNameWithLength.Split('-').First();
                            fileLength = Convert.ToInt64(fileNameWithLength.Split('-').Last());
                        }
                    }
                }
                catch (Exception ex)
                {
                    Message.AppendText("系統異常..." + ex.Message);
                    break;
                }
            }
        }

        private void SendMessage_Click(object sender, EventArgs e)
        {
            ServerSend(XiaoXi.Text,0);
        }

        private void ServerSend(string SendStr, byte symbol)
        {
            //用UTF8能接受文字資訊
            byte[] buffer = Encoding.UTF8.GetBytes(SendStr);
            //實際傳送的位元組陣列比實際輸入的長度多1,用於存取識別符號
            byte[] newBuffer = new byte[buffer.Length + 1];
            //識別符號新增在位置為0的地方
            newBuffer[0] = symbol;
            Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);
            if (!string.IsNullOrEmpty(ClientList.Text.Trim()))
            {
                dicSocket[ClientList.Text.Trim()].Send(newBuffer);
                Message.AppendText("您在 " + GetTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客戶端傳送了:\r\n" + SendStr + "\r\n");
            }
            else
            {
                for (int i = 0; i < ClientList.Items.Count; i++)
                {
                    dicSocket[ClientList.Items[i].ToString()].Send(newBuffer);
                }
                Message.AppendText("您在 " + GetTime() + " 群發了資訊:\r\n" + SendStr + " \r\n");
            }
            XiaoXi.Text = null;
            
        }

        string filePath = null;
        string fileName = null;
        private void SelectFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofDialog = new OpenFileDialog();
            if(ofDialog.ShowDialog(this) == DialogResult.OK)
            {
                fileName = ofDialog.SafeFileName;//獲取選取檔案的檔名
                FileName.Text = fileName;//將檔名顯示在文字框上
                filePath = ofDialog.FileName;//獲取包含檔名的全路徑
            }
        }

        private void SendFile_Click(object sender, EventArgs e)
        {
            sendFile(filePath);
        }

        private void sendFile(string fileFullPath)
        {
            if (string.IsNullOrEmpty(fileFullPath))
            {
                MessageBox.Show(@"請選擇需要傳送的檔案!");
                return;
            }

            //傳送檔案前,將檔名和長度發過去
            long fileLength = new FileInfo(fileFullPath).Length;
            string totalMsg = string.Format("{0}-{1}", fileName, fileLength);
            ServerSend(totalMsg, 2);

            byte[] buffer = new byte[8 * 1024];

            using (FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read))
            {
                int readLength = 0;
                bool firstRead = true;
                long sentFileLength = 0;
                while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)
                {
                    sentFileLength += readLength;
                    //第一次傳送的位元組流上加個字首1
                    if (firstRead)
                    {
                        byte[] firstBuffer = new byte[readLength + 1];
                        //標記1,代表為檔案
                        firstBuffer[0] = 1;
                        Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);
                        if (!string.IsNullOrEmpty(ClientList.Text.Trim()))
                        {
                            dicSocket[ClientList.Text.Trim()].Send(firstBuffer, 0, readLength + 1, SocketFlags.None);
                            Message.AppendText("您在 " + GetTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客戶端傳送了:\r\n" + fileName + "\r\n");
                        }
                        else
                        {
                            for (int i = 0; i < ClientList.Items.Count; i++)
                            {
                                dicSocket[ClientList.Items[i].ToString()].Send(firstBuffer, 0, readLength + 1, SocketFlags.None);
                            }
                            Message.AppendText("您在 " + GetTime() + " 群發了檔案:\r\n" + fileName + " \r\n");
                        }
                        FileName.Text = null;
                        firstRead = false;
                        continue;
                    }
                    if (!string.IsNullOrEmpty(ClientList.Text.Trim()))
                    {
                        dicSocket[ClientList.Text.Trim()].Send(buffer, 0, readLength + 1, SocketFlags.None);
                        Message.AppendText("您在 " + GetTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的客戶端傳送了:\r\n" + fileName + "\r\n");
                    }
                    else
                    {
                        for (int i = 0; i < ClientList.Items.Count; i++)
                        {
                            dicSocket[ClientList.Items[i].ToString()].Send(buffer, 0, readLength + 1, SocketFlags.None);
                        }
                        Message.AppendText("您在 " + GetTime() + " 群發了檔案:\r\n" + fileName + " \r\n");
                    }
                    FileName.Text = null;
                }
                fs.Close();
            }
        }


        public DateTime GetTime()//獲取系統時間
        {
            DateTime now = new DateTime();
            now = DateTime.Now;
            return now;
        }

        private void Server_Load(object sender, EventArgs e)
        {
            IP.AppendText("127.0.0.1");
            Port.AppendText("5555");
        }

        private void choose_Click(object sender, EventArgs e)
        {
            ClientList.SelectedItem = null;
        }

    }
}