zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    无线Mesh网络技术基础与应用
    BLE低功耗蓝牙关键技术解析与应用
    Android Studio NDK开发入门
    Android 注解的使用与注意事项
    图形图像处理库大全
    vs2010下C++调用lib或dll文件
    网线连接电脑共享文件传递
    分配和释放 BSTR 的内存
    #include <objsafe.h>//OCX控件在IE8浏览器下不能使用问题
    彻底搞定char/wchar_t/unicode
  • 原文地址:https://www.cnblogs.com/kellen451/p/7127670.html
Copyright © 2011-2022 走看看