c#Socket Tcp服務端編程


 

創建一個socket服務類,綁定監聽端口,

然后創建一個線程listen連接的客戶端,

把監聽到的客戶端加入dictionary里面,以便於管理,

同時創建receive線程,循環接收數據加入list緩存區,解決粘包或者分包的情況,

關閉服務時,需要將連接上的socket逐個shutdown。

 

/*
 *
 * 該類用於管理tcp連接通訊
 * 
 */

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace Communication
{
    /// <summary>
    /// 服務端
    /// </summary>
    public class MyTcpServer
    {

        private Socket ServerSocket = null;//服務端  
        public Dictionary<string, MySession> dic_ClientSocket = new Dictionary<string, MySession>();//tcp客戶端字典
        private Dictionary<string, Thread> dic_ClientThread = new Dictionary<string, Thread>();//線程字典,每新增一個連接就添加一條線程
        private bool Flag_Listen = true;//監聽客戶端連接的標志

        /// <summary>
        /// 啟動服務
        /// </summary>
        /// <param name="port">端口號</param>
        public bool OpenServer(int port)
        {
            try
            {
                Flag_Listen = true;
                // 創建負責監聽的套接字,注意其中的參數;
                ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                // 創建包含ip和端口號的網絡節點對象;
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port);
                try
                {
                    // 將負責監聽的套接字綁定到唯一的ip和端口上;
                    ServerSocket.Bind(endPoint);
                }
                catch
                {
                    return false;
                }
                // 設置監聽隊列的長度;
                ServerSocket.Listen(100);
                // 創建負責監聽的線程;
                Thread Thread_ServerListen = new Thread(ListenConnecting);
                Thread_ServerListen.IsBackground = true;
                Thread_ServerListen.Start();

                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 關閉服務
        /// </summary>
        public void CloseServer()
        {
            lock (dic_ClientSocket)
            {
                foreach (var item in dic_ClientSocket)
                {
                    item.Value.Close();//關閉每一個連接
                }
                dic_ClientSocket.Clear();//清除字典
            }
            lock (dic_ClientThread)
            {
                foreach (var item in dic_ClientThread)
                {
                    item.Value.Abort();//停止線程
                }
                dic_ClientThread.Clear();
            }
            Flag_Listen = false;
            //ServerSocket.Shutdown(SocketShutdown.Both);//服務端不能主動關閉連接,需要把監聽到的連接逐個關閉
            if (ServerSocket != null)
                ServerSocket.Close();

        }
        /// <summary>
        /// 監聽客戶端請求的方法;
        /// </summary>
        private void ListenConnecting()
        {
            while (Flag_Listen)  // 持續不斷的監聽客戶端的連接請求;
            {
                try
                {
                    Socket sokConnection = ServerSocket.Accept(); // 一旦監聽到一個客戶端的請求,就返回一個與該客戶端通信的 套接字;
                    // 將與客戶端連接的 套接字 對象添加到集合中;
                    string str_EndPoint = sokConnection.RemoteEndPoint.ToString();
                    MySession myTcpClient = new MySession() { TcpSocket = sokConnection };
                    //創建線程接收數據
                    Thread th_ReceiveData = new Thread(ReceiveData);
                    th_ReceiveData.IsBackground = true;
                    th_ReceiveData.Start(myTcpClient);
                    //把線程及客戶連接加入字典
                    dic_ClientThread.Add(str_EndPoint, th_ReceiveData);
                    dic_ClientSocket.Add(str_EndPoint, myTcpClient);
                }
                catch
                {

                }
                Thread.Sleep(200);
            }
        }
        /// <summary>
        /// 接收數據
        /// </summary>
        /// <param name="sokConnectionparn"></param>
        private void ReceiveData(object sokConnectionparn)
        {
            MySession tcpClient = sokConnectionparn as MySession;
            Socket socketClient = tcpClient.TcpSocket;
            bool Flag_Receive = true;

            while (Flag_Receive)
            {
                try
                {
                    // 定義一個2M的緩存區;
                    byte[] arrMsgRec = new byte[1024 * 1024 * 2];
                    // 將接受到的數據存入到輸入  arrMsgRec中;
                    int length = -1;
                    try
                    {
                        length = socketClient.Receive(arrMsgRec); // 接收數據,並返回數據的長度;
                    }
                    catch
                    {
                        Flag_Receive = false;
                        // 從通信線程集合中刪除被中斷連接的通信線程對象;
                        string keystr = socketClient.RemoteEndPoint.ToString();
                        dic_ClientSocket.Remove(keystr);//刪除客戶端字典中該socket
                        dic_ClientThread[keystr].Abort();//關閉線程
                        dic_ClientThread.Remove(keystr);//刪除字典中該線程

                        tcpClient = null;
                        socketClient = null;
                        break;
                    }
                    byte[] buf = new byte[length];
                    Array.Copy(arrMsgRec, buf, length);
                    lock (tcpClient.m_Buffer)
                    {
                        tcpClient.AddQueue(buf);
                    }
                }
                catch
                {

                }
                Thread.Sleep(100);
            }
        }
        /// <summary>
        /// 發送數據給指定的客戶端
        /// </summary>
        /// <param name="_endPoint">客戶端套接字</param>
        /// <param name="_buf">發送的數組</param>
        /// <returns></returns>
        public bool SendData(string _endPoint, byte[] _buf)
        {
            MySession myT = new MySession();
            if (dic_ClientSocket.TryGetValue(_endPoint, out myT))
            {
                myT.Send(_buf);
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    /// <summary>
    /// 會話端
    /// </summary>
    public class MySession
    {
        public Socket TcpSocket;//socket對象
        public List<byte> m_Buffer = new List<byte>();//數據緩存區

        public MySession()
        {

        }

        /// <summary>
        /// 發送數據
        /// </summary>
        /// <param name="buf"></param>
        public void Send(byte[] buf)
        {
            if (buf != null)
            {
                TcpSocket.Send(buf);
            }
        }
        /// <summary>
        /// 獲取連接的ip
        /// </summary>
        /// <returns></returns>
        public string GetIp()
        {
            IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint;
            string _ip = clientipe.Address.ToString();
            return _ip;
        }
        /// <summary>
        /// 關閉連接
        /// </summary>
        public void Close()
        {
            TcpSocket.Shutdown(SocketShutdown.Both);
        }
        /// <summary>
        /// 提取正確數據包
        /// </summary>
        public byte[] GetBuffer(int startIndex, int size)
        {
            byte[] buf = new byte[size];
            m_Buffer.CopyTo(startIndex, buf, 0, size);
            m_Buffer.RemoveRange(0, startIndex + size);
            return buf;
        }

        /// <summary>
        /// 添加隊列數據
        /// </summary>
        /// <param name="buffer"></param>
        public void AddQueue(byte[] buffer)
        {
            m_Buffer.AddRange(buffer);
        }
        /// <summary>
        /// 清除緩存
        /// </summary>
        public void ClearQueue()
        {
            m_Buffer.Clear();
        }
    }
}

 

 

the end


免責聲明!

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



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