(C#:Socket)簡單的服務端與客戶端通信。


要求:
1.可以完成一對一的通信;
2.實現服務端對客戶端一對多的選擇發送;
3.可以實現服務端的群發功能;
4.可以實現客戶端文件的發送;

要點:
服務器端:
第一步:用指定的端口號和服務器的ip建立一個EndPoint對像;
第二步:建立一個Socket對像;
第三步:用socket對像的Bind()方法綁定EndPoint;
第四步:用socket對像的Listen()方法開始監聽;
第五步:接受到客戶端的連接,用socket對像的Accept()方法創建新的socket對像用於和請求的客戶端進行通信;
第六步:通信結束后一定記得關閉socket;

客戶端:
第一步:用指定的端口號和服務器的ip建立一個EndPoint對像;
第二步:建立一個Socket對像;
第三步:用socket對像的Connect()方法以上面建立的EndPoint對像做為參數,向服務器發出連接請求;
第四步:如果連接成功,就用socket對像的Send()方法向服務器發送信息;
第五步:用socket對像的Receive()方法接受服務器發來的信息 ;
第六步:通信結束后一定記得關閉socket;

服務端代碼如下:

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 Socket_ServerAndClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }

        Thread threadWatch = null;
        Socket socketWatch = null;

        /// <summary>
        /// 創建服務
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
            IPEndPoint endpoint = new IPEndPoint(address,int.Parse(txtPort.Text.Trim()));
            socketWatch.Bind(endpoint);
            socketWatch.Listen(10);
            threadWatch = new Thread(WatchConnection);
            threadWatch.IsBackground = true;
            threadWatch.Start();           
            ShowMsg("服務器監聽成功......");
        }

        
        //Socket sokConnection = null;
        Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
        Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();

        /// <summary>
        /// 監聽客戶端的請求方法
        /// </summary>
        /// <param name="obj"></param>
        private void WatchConnection(object obj)
        {
            while (true)
            {
                // 負責通信的套接字
                Socket sokConnection = socketWatch.Accept();
                lb_Online.Items.Add(sokConnection.RemoteEndPoint.ToString());
                dict.Add(sokConnection.RemoteEndPoint.ToString(),sokConnection);
                
                //創建通信線程
                ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);// 委托
                Thread thr = new Thread(pts);
                thr.IsBackground = true;
                thr.Start(sokConnection);
                dictThread.Add(sokConnection.RemoteEndPoint.ToString(),thr);

                ShowMsg("客戶端連接成功......"+sokConnection.RemoteEndPoint.ToString());
            }           
        }

        /// <summary>
        /// 服務端負責監聽客戶端發送消息的方法
        /// </summary>
        void RecMsg(object socketClient)
        {
            Socket socketClients = socketClient as Socket;
            while (true)
            {
                byte[] arrMsgRec = new byte[1024 * 1024 * 2];

                int length = -1;
                try
                {
                    length = socketClients.Receive(arrMsgRec);
                }
                catch (SocketException ex)
                {
                    ShowMsg("異常:" + ex.Message);
                    // 從 通信套接字 集合中刪除被中斷連接的套接字對象
                    dict.Remove(socketClients.RemoteEndPoint.ToString());
                    // 從 通信線程 集合中刪除被中斷連接的套接字對象
                    dictThread.Remove(socketClients.RemoteEndPoint.ToString());
                    // 從 列表 中移除 IP&Port
                    lb_Online.Items.Remove(socketClients.RemoteEndPoint.ToString());
                    break;
                }
                catch (Exception ex)
                {
                    ShowMsg("異常:" + ex.Message);
                    break;
                }
                // 判斷第一個發送過來的數據如果是1,則代表發送過來的是文本數據
                if (arrMsgRec[0] == 0)
                {
                    string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length-1);
                    ShowMsg(strMsgRec);
                }
                // 若是1則發送過來的是文件數據(文檔,圖片,視頻等。。。)
                else if(arrMsgRec[0] == 1)
                {
                    // 保存文件選擇框對象
                    SaveFileDialog sfd = new SaveFileDialog();
                    // 選擇文件路徑
                    if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        // 獲得保存文件的路徑
                        string fileSavePath = sfd.FileName;
                        // 創建文件流,然后讓文件流根據路徑創建一個文件
                        using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
                        {
                            fs.Write(arrMsgRec, 1, length - 1);
                            ShowMsg("文件保存成功:"+fileSavePath);
                        }
                    }
                }               
            }
        }

        private void ShowMsg(string p)
        {
            txtMsg.AppendText(p+"\r\n");
        }

        /// <summary>
        /// 發送消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Send_Click_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(lb_Online.Text))
            {
                MessageBox.Show("請選擇發送的好友!!!");
            }
            else
            { 
                string strMsg = tb_Msg_Send.Text.Trim();
                byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
                string strClientKey = lb_Online.Text;
                try
                {
                    dict[strClientKey].Send(arrMsg);
                    ShowMsg("發送了數據出去:"+strMsg);
                }
                catch (SocketException ex)
                {
                    ShowMsg("發送時異常:" + ex.Message);
                }
                catch(Exception ex)
                {
                    ShowMsg("發送時異常:" + ex.Message);
                }
                // sokConnection.Send(arrMsg);
                ShowMsg("發送了數據出去:"+strMsg);
            }
        }

        /// <summary>
        /// 群發消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SendToAll_Click(object sender, EventArgs e)
        {
            string strMsg = txtMsg.Text.Trim();
            byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
            foreach (Socket item in dict.Values)
            {
                item.Send(arrMsg);
            }
            ShowMsg("群發完畢!!!:)");
        }
    }
}

  

客戶端代碼如下:

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 Socket_Client
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }

        Thread threadRec = null;
        Socket socketClient = null;

        private void btn_Connect_Click(object sender, EventArgs e)
        {
            IPAddress address = IPAddress.Parse(tb_IP.Text.Trim());
            IPEndPoint endport = new IPEndPoint(address,int.Parse(tb_Port.Text.Trim()));
            socketClient = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            socketClient.Connect(endport);

            threadRec = new Thread(RecMsg);
            threadRec.IsBackground = true;
            threadRec.Start();
        }

        void RecMsg()
        {
            while (true)
            {
                byte[] arrMsgRec = new byte[1024*1024*2];
                int length = socketClient.Receive(arrMsgRec);
                string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec,0,length);
                ShowMsg(strMsgRec);
            }
        }


        private void ShowMsg(string msg)
        {
            tb_Msg.AppendText(msg+"\r\n");
        }

        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            string strMsg = txtMsgSend.Text.Trim();
            byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
            byte[] arrMsgSend = new byte[arrMsg.Length];
            // 添加標識位,0代表發送的是文字
            arrMsgSend[0] = 0;
            Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length);
            socketClient.Send(arrMsg);
            ShowMsg("I say:"+strMsg);
        }

        /// <summary>
        /// 選擇文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btChoseFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                txtFilePath.Text = ofd.FileName;
            }
        }

        /// <summary>
        /// 發送文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btSendFile_Click(object sender, EventArgs e)
        {
            using (FileStream fs = new FileStream())
            { 
                byte[] arrFile = new byte[1024*1024*2];
                int length = fs.Read(arrFile, 0, arrFile.Length);
                byte[] arrFileSend = new byte[length+1];
                arrFileSend[0] = 1;// 代表文件數據
                // 將數組 arrFile 里的數據從第零個數據拷貝到 數組 arrFileSend 里面,從第1個開始,拷貝length個數據
                Buffer.BlockCopy(arrFile, 0, arrFileSend, 1, length);
                socketClient.Send(arrFileSend);
            }
        }
    }
}

程序運行截圖:

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM