• TCP Socket服务端客户端(二)


    本文服务端客户端封装代码转自https://blog.csdn.net/zhujunxxxxx/article/details/44258719,并作了简单的修改。

    1)服务端

    此类主要处理服务端相关消息

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    namespace TcpSocketServer
    {
        /// <summary>
        /// Socket异步TCP服务器
        /// 建议把close方法改为私有,即服务端不主动关闭连接
        /// 客户端主动关闭连接后,其receive仍在
        /// </summary>
        public class TCPServerAsync : IDisposable
        {
            #region Fields 
            private int _maxClient;// 服务器程序允许的最大客户端连接数
            private int _clientCount;// 当前的连接的客户端数 
     
            private Socket _serverSock;// 服务器使用的异步socket
      
            private List<ClientInfo> _clients;// 客户端会话列表
            private bool disposed = false;//内存释放
            #endregion
            #region Properties 
            public bool IsRunning { get; private set; }// 服务器是否正在运行 
            public IPAddress Address { get; private set; }// 监听的IP地址 
            public int Port { get; private set; }// 监听的端口 
     
            public Encoding Encoding { get; set; }// 通信使用的编码
            #endregion
     
            #region 构造函数 
            /// <summary> 
            /// 异步Socket TCP服务器 
            /// </summary> 
            public TCPServerAsync(int listenPort)
                : this(IPAddress.Any, listenPort, 1024)
            {
            }
            public TCPServerAsync(IPEndPoint localEP)
                : this(localEP.Address, localEP.Port, 1024)
            {
            }
            public TCPServerAsync(IPAddress localIPAddress, int listenPort, int maxClient)
            {
                this.Address = localIPAddress;
                this.Port = listenPort;
                this.Encoding = Encoding.Default;
                _maxClient = maxClient;
                _clients = new List<ClientInfo>();
                _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            }
            #endregion
            #region Method 
            /// <summary> 
            /// 启动服务器 
            /// </summary> 
            public void Start()
            {
                if (!IsRunning)
                {
                    IsRunning = true;
                    _serverSock.Bind(new IPEndPoint(this.Address, this.Port));
                    _serverSock.Listen(1024);
                    _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);
                }
            }
            /// <summary> 
            /// 启动服务器 
            /// </summary> 
            /// <param name="backlog"> 
            /// 服务器所允许的挂起连接序列的最大长度 
            /// </param> 
            public void Start(int backlog)
            {
                if (!IsRunning)
                {
                    IsRunning = true;
                    _serverSock.Bind(new IPEndPoint(this.Address, this.Port));
                    _serverSock.Listen(backlog);
                    _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);
                }
            }
            /// <summary> 
            /// 停止服务器 
            /// </summary> 
            public void Stop()
            {
                if (IsRunning)
                {
                    IsRunning = false;
                    _serverSock.Close();
                    //TODO 关闭对所有客户端的连接 
                    CloseAllClient();
                }
            }
            #region Close 
            /// <summary> 
            /// 关闭一个与客户端之间的会话 
            /// </summary> 
            /// <param name="state">需要关闭的客户端会话对象</param> 
            public void Close(ClientInfo state)
            {
                if (state != null)
                {
                    //state.Datagram = null;
                    state.RecvDataBuffer = null;
                    _clients.Remove(state);
                    _clientCount--;
                    //TODO 触发关闭事件 
                    state.Close();
                }
            }
            /// <summary> 
            /// 关闭所有的客户端会话,与所有的客户端连接会断开 
            /// </summary> 
            public void CloseAllClient()
            {
                foreach (ClientInfo client in _clients)
                {
                    Close(client);
                }
                _clientCount = 0;
                _clients.Clear();
            }
            #endregion
            /// <summary> 
            /// 处理客户端连接 
            /// </summary> 
            /// <param name="ar"></param> 
            private void HandleAcceptConnected(IAsyncResult ar)
            {
                if (IsRunning)
                {
                    Socket server = (Socket)ar.AsyncState;
                    Socket client = server.EndAccept(ar);
                    //检查是否达到最大的允许的客户端数目 
                    if (_clientCount >= _maxClient)
                    {
                        //C-TODO 触发事件 
                        RaiseOtherException(null);
                    }
                    else
                    {
                        ClientInfo state = new ClientInfo(client);
                        lock (_clients)
                        {
                            _clients.Add(state);
                            _clientCount++;
                            RaiseClientConnected(state); //触发客户端连接事件 
                        }
                        state.RecvDataBuffer = new byte[client.ReceiveBufferSize];
                        //开始接受来自该客户端的数据 
                        client.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None,
                         new AsyncCallback(HandleDataReceived), state);
                    }
                    //接受下一个请求 
                    server.BeginAccept(new AsyncCallback(HandleAcceptConnected), ar.AsyncState);
                }
            }
            /// <summary> 
            /// 处理客户端数据 
            /// </summary> 
            /// <param name="ar"></param> 
            private void HandleDataReceived(IAsyncResult ar)
            {
                if (IsRunning)
                {
                    ClientInfo state = (ClientInfo)ar.AsyncState;
                    Socket client = state.ClientSocket;
                    try
                    {
                        //异步接收,当客户端退出的时候会再次执行EndReceive                     
                        int recv = client.EndReceive(ar);
         //客户端主动断开连接时(采用close关闭)recv == 0
         //所以执行回掉RaiseClientDisconnected,并在回掉函数中关闭连接
         //以不在RaiseClientDisconnected回掉中关闭连接为优,即直接调用Close关闭
         if (recv == 0)
                        {
                            //C- TODO 触发事件 (关闭客户端) 
                            //Close(state);
                            RaiseClientDisconnected(state);
                            return;
                        }
                        //TODO 处理已经读取的数据 ps:数据在state的RecvDataBuffer中 
                        state._recvdBufferLength = recv;
                        //C- TODO 触发数据接收事件 
                        RaiseDataReceived(state);
                    }
                    catch (SocketException)
                    {
                        //C- TODO 异常处理 
                        RaiseNetError(state);
         //客户端主动断开连接时(直接关闭程序,而非采用close关闭)引发以尝
         //所以执行回掉RaiseClientDisconnected,并在回掉函数中关闭连接
         //以不在回掉中关闭连接为优,直接/Close(state)关闭
         state._recvdBufferLength = 0;
                        RaiseClientDisconnected(state);
                        return;
                    }
                    //继续接收来自来客户端的数据
                    //ps: 如果未接收到数据则始终处于挂起状态;
                    //pss:当收到close消息,server主动关闭连接(212行RaiseDataReceived中进行了关闭)时由于已经关闭连接,所以下述代码会有异常
                    //后续可在应用只要不是通过客户端发消息主动close就可避免此问题,所以在此加一个异常处理,或者加一个bool变量判断是否断掉
                    try
                    {
                        client.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None,
                         new AsyncCallback(HandleDataReceived), state);
                    }
                    catch{}  
                }
            }
            /// <summary> 
            /// 发送数据 
            /// </summary> 
            /// <param name="state">接收数据的客户端会话</param> 
            /// <param name="data">数据报文</param> 
            public void Send(ClientInfo state, byte[] data)
            {
                RaisePrepareSend(state);
                Send(state.ClientSocket, data);
            }
            /// <summary> 
            /// 异步发送数据至指定的客户端 
            /// </summary> 
            /// <param name="client">客户端</param> 
            /// <param name="data">报文</param> 
            public void Send(Socket client, byte[] data)
            {
                if (!IsRunning)
                    throw new InvalidProgramException("This TCP Scoket server has not been started.");
                if (client == null)
                    throw new ArgumentNullException("client");
                if (data == null)
                    throw new ArgumentNullException("data");
                client.BeginSend(data, 0, data.Length, SocketFlags.None,
                 new AsyncCallback(SendDataEnd), client);
            }
            /// <summary> 
            /// 发送数据完成处理函数 
            /// </summary> 
            /// <param name="ar">目标客户端Socket</param> 
            private void SendDataEnd(IAsyncResult ar)
            {
                ((Socket)ar.AsyncState).EndSend(ar);
                RaiseCompletedSend(new TcpSocketServer.ClientInfo((Socket)ar.AsyncState));
            }
            #endregion
            #region 事件 
            #region 客户端连接事件
            public event EventHandler<TCPMessageArgs> ClientConnecting;//客户端正在连接事件
            public event EventHandler<TCPMessageArgs> ClientConnected; //客户端连接事件    
            public event EventHandler<TCPMessageArgs> ClientDisconnected;//客户端断开连接
            //挂起事件
            private void RaiseClientConnecting(ClientInfo state)
            {
                if(ClientConnecting!=null)
                {
                    ClientConnecting(this, new TCPMessageArgs(state));
                }
            }
            private void RaiseClientConnected(ClientInfo state)
            {
                if (ClientConnected != null)
                {
                    ClientConnected(this, new TCPMessageArgs(state));
                }
            }
            private void RaiseClientDisconnected(ClientInfo state)
            {
                if (ClientDisconnected != null)
                {
                    ClientDisconnected(this, new TCPMessageArgs(state));
                }
            }
            #endregion
            #region 数据发送事件
            public event EventHandler<TCPMessageArgs> PrepareSend;//数据准备发送事件
            public event EventHandler<TCPMessageArgs> DataSending;//数据正在发送事件
            public event EventHandler<TCPMessageArgs> CompletedSend;//数据发送结束事件
            public event EventHandler<TCPMessageArgs> DataReceived;//接受到客户端数据事件
            //挂起事件
            private void RaisePrepareSend(ClientInfo state)
            {
                if (PrepareSend != null)
                {
                    PrepareSend(this, new TCPMessageArgs(state));
                }
            }
            private void RaiseDataSending(ClientInfo state)
            {
                if (PrepareSend != null)
                {
                    DataSending(this, new TCPMessageArgs(state));
                }
            }
            private void RaiseDataReceived(ClientInfo state)
            {
                if (DataReceived != null)
                {
                    DataReceived(this, new TCPMessageArgs(state));
                }
            }
            private void RaiseCompletedSend(ClientInfo state)
            {
                if (CompletedSend != null)
                {
                    CompletedSend(this, new TCPMessageArgs(state));
                }
            }
            #endregion
            #region 关闭连接事件
            public event EventHandler<TCPMessageArgs> ClientClose;//关闭客户端事件
            public event EventHandler<TCPMessageArgs> AllClientsClose;//关闭所有客户端事件
            //挂起事件
            private void RaiseClientClose(ClientInfo state)
            {
                if(ClientClose!=null)
                {
                    ClientClose(this, new TcpSocketServer.TCPMessageArgs(state));
                }
            }
            private void RaiseAllClientClose(ClientInfo state)
            {
                if (AllClientsClose != null)
                {
                    AllClientsClose(this, new TcpSocketServer.TCPMessageArgs(state));
                }
            }
            #endregion
            #region 其他事件
            public event EventHandler<TCPMessageArgs> NetError;// 网络错误事件
            public event EventHandler<TCPMessageArgs> OtherException;//其他异常
            //挂起事件
            private void RaiseNetError(ClientInfo state)
            {
                if (OtherException != null)
                {
                    OtherException(this, new TCPMessageArgs(state));
                }
            }
            private void RaiseOtherException(ClientInfo state)
            {
                RaiseOtherException(state);
            }
            #endregion
            #endregion
            #region 释放 
            /// <summary> 
            /// Performs application-defined tasks associated with freeing,  
            /// releasing, or resetting unmanaged resources. 
            /// </summary> 
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
            /// <summary> 
            /// Releases unmanaged and - optionally - managed resources 
            /// </summary> 
            /// <param name="disposing"><c>true</c> to release  
            /// both managed and unmanaged resources; <c>false</c>  
            /// to release only unmanaged resources.</param> 
            protected virtual void Dispose(bool disposing)
            {
                if (!this.disposed)
                {
                    if (disposing)
                    {
                        try
                        {
                            Stop();
                            if (_serverSock != null)
                            {
                                _serverSock = null;
                            }
                        }
                        catch (SocketException)
                        {
                            //TODO 
                            RaiseOtherException(null);
                        }
                    }
                    disposed = true;
                }
            }
            #endregion
        }
    }

    2)客户端

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    
    namespace TcpSocketClient
    {
        public class TCPClientAsync
        {
            #region 字段
    
            private Socket clientSock;
    
            //private byte[] recvBuffer;
    
            private ClientInfo state;
    
            #endregion
    
            #region 属性
    
            public IPAddress Address { get; private set; }// 监听的IP地址  
    
            public int Port { get; private set; }// 监听的端口  
            public bool IsConnected { get;private set; }
    
            #endregion
    
            #region 构造方法
    
            public TCPClientAsync(IPAddress ipAddress,int port)
            {
                this.Address = ipAddress;
                this.Port = port;
                clientSock=new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            }
    
            public TCPClientAsync(IPEndPoint ipEndPort)
                :this(ipEndPort.Address,ipEndPort.Port)
            {
            }
    
            #endregion
    
            #region Method
    
            public void Connect()//开始连接
            {
                if(!IsConnected)
                {
                    //clientSock.BeginConnect(Address, Port, new AsyncCallback(HandleConnectAccepted), clientSock);
                    clientSock.BeginConnect(Address, Port, iAsyncResult=>
                    {
                        try
                        {
                            clientSock.EndConnect(iAsyncResult);
                            IsConnected = true;
                            state = new TcpSocketClient.ClientInfo(clientSock);
                            RaiseConnectAccepted(state);//挂起连接事件
                        }
                        catch
                        {
                            //TODO连接失败
                            RaiseConnectFailed();
                        }
                        
                    }, null);
                }            
            }
    
            //private void HandleConnectAccepted(IAsyncResult iAsyncResult)
            //{
            //    clientSock.EndConnect(iAsyncResult);
            //    IsConnected = true;
            //}
    
            public void Send(byte[] data)
            {
                if (!IsConnected) return;
    
                //clientSock.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(HandleDataSend), null);
                clientSock.BeginSend(data, 0, data.Length, SocketFlags.None, iAsyncResult=>
                {
                    clientSock.EndSend(iAsyncResult);
    
                    RaiseDataSend(state);
                }, null);
            }
    
            public void Receive()
            {
                if (!IsConnected) return;
    
                state.RecvDataBuffer = new byte[clientSock.ReceiveBufferSize];
                clientSock.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None, new AsyncCallback(HandleDataReceive), null);
            }
    
            private void HandleDataReceive(IAsyncResult iAsyncResult)
            {
                int recv = 0;
                try
                {
                    recv = clientSock.EndReceive(iAsyncResult);
    
                    if (recv == 0)//客户端主动断开连接时recv=0
                    {
                        Close();
                        RaiseServerCloseLink();
                        return;
                    }
    
                    state._recvdBufferLength = recv;
    
                    RaiseDataReceived(state);
                }
                catch(Exception ex)
                {
                    //TODO 信息获取失败
                    string str = ex.Message;
                    return;
                }
    
                //if (!IsConnected) return;
                clientSock.BeginReceive(state.RecvDataBuffer, 0, state.RecvDataBuffer.Length, SocketFlags.None, new AsyncCallback(HandleDataReceive), null);
            }
            //private void HandleDataSend(IAsyncResult iAsyncResult)
            //{
            //    clientSock.EndSend(iAsyncResult);
            //}
    
            public void Close()
            {
                //关闭数据的接受和发送  
                clientSock.Shutdown(SocketShutdown.Both);
    
                //清理资源  
                clientSock.Close();
    
                state = null;
                IsConnected = false;
                GC.Collect();
            }
            #endregion
    
            #region 事件
    
            public event EventHandler<TCPMessageArgs> ConnectAccepted;//连接事件 
    
            public event EventHandler<TCPMessageArgs> DataSend;//数据发送事件  
    
            public event EventHandler<TCPMessageArgs> DataReceived;//数据发送事件
    
            public event EventHandler<TCPMessageArgs> ErrorException;//错误信息
    
            public event EventHandler<TCPMessageArgs> ServerCloseLink;//服务端关闭连接
    
            public event EventHandler<TCPMessageArgs> ConnectFailed;//连接失败
    
            private void RaiseConnectAccepted(ClientInfo state)
            {
                if (ConnectAccepted != null)
                {
                    ConnectAccepted(this, new TCPMessageArgs(state));
                }
            }
    
            private void RaiseDataSend(ClientInfo state)
            {
                if (DataSend != null)
                {
                    DataSend(this, new TcpSocketClient.TCPMessageArgs(state));
                }
            }
    
            private void RaiseDataReceived(ClientInfo state)
            {
                if(DataReceived!=null)
                {
                    DataReceived(this, new TcpSocketClient.TCPMessageArgs(state));
                }
            }
    
            private void RaiseErrorException()
            {
                if(ErrorException!=null)
                {
                    ErrorException(this, null);
                }
            }
    
            private void RaiseServerCloseLink()
            {
                if(ServerCloseLink!=null)
                {
                    ServerCloseLink(this, null);
                }
            }
    
            private void RaiseConnectFailed()
            {
                if(ConnectFailed!=null)
                {
                    ConnectFailed(this,null);
                }
            }
    
            #endregion
        }
    }

    3)消息类

    此类存储相关消息

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TcpSocketServer
    {
        /// <summary>
        /// Socket TCP事件参数
        /// </summary>
        public class TCPMessageArgs : EventArgs
        {
            /// <summary>  
            /// 提示信息  
            /// </summary>  
            public string _msg;
    
            /// <summary>  
            /// 客户端状态封装类  
            /// </summary>  
            public ClientInfo state;
    
            /// <summary>  
            /// 是否已经处理过了  
            /// </summary>  
           // public bool IsHandled { get; set; }
    
            public TCPMessageArgs(string msg)
            {
                this._msg = msg;
                //IsHandled = false;
            }
            public TCPMessageArgs(ClientInfo state)
            {
                this.state = state;
                // IsHandled = false;
            }
            public TCPMessageArgs(string msg, ClientInfo state)
            {
                this._msg = msg;
                this.state = state;
                //IsHandled = false;
            }
        }
    }

    4)服务端存储所有客户端类

    通过

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Xml;
    
    namespace TcpSocketServer
    {
        
        /// <summary>
        /// 客户端信息
        /// </summary>
        public class ClientInfo
        {
            #region 字段 
    
            public int _recvdBufferLength;//接收到的数据长度
    
            private byte[] _recvBuffer;// 接收数据缓冲区  
    
            private string _datagram;// 客户端发送到服务器的报文 
      
            private Socket _clientSock;// 客户端的Socket
    
            private string tempMsg = string.Empty;
    
            #endregion
    
            #region 属性  
    
            /// <summary>  
            /// 接收数据缓冲区   
            /// </summary>  
            public byte[] RecvDataBuffer
            {
                get
                {
                    return _recvBuffer;
                }
                set
                {
                    _recvBuffer = value;
                }
            }
    
            /// <summary>  
            /// 存取会话的报文  
            /// </summary>  
            public string Datagram
            {
                get
                {
                    _datagram = Encoding.Default.GetString(_recvBuffer, 0, _recvdBufferLength);
                    return _datagram;
                }
            }
    
            public List<MsgProtocol> MsgList
            {
                get
                {
                    _datagram = Encoding.Default.GetString(_recvBuffer, 0, _recvdBufferLength);
                    return HandlerRecvdString(_datagram);
                }
            }
    
    
            /// <summary>  
            /// 获得与客户端会话关联的Socket对象  
            /// </summary>  
            public Socket ClientSocket
            {
                get
                {
                    return _clientSock;
                }
            }
    
            #endregion
    
            public ClientInfo(Socket clientSocket)
            {
                _clientSock = clientSocket;
            }
    
     
            public void Close()
            {
                //关闭数据的接受和发送  
                _clientSock.Shutdown(SocketShutdown.Both);
    
                //清理资源  
                _clientSock.Close();
            }
    
            public List<MsgProtocol> HandlerRecvdString(string msg)
            {
                List<MsgProtocol> msgProList = new List<MsgProtocol>();
                if (!String.IsNullOrEmpty(tempMsg))
                {
                    msg = tempMsg + msg;
                }
                string pattern = "(^<protocol>.*?</protocol>)";
                if (Regex.IsMatch(msg, pattern))
                {
                    //匹配协议内容
                    string message = Regex.Match(msg, pattern).Groups[0].Value;
                    //将匹配的内容添加到集合
                    msgProList.Add(HandleMsg(message));
                    tempMsg = string.Empty;
                    //截取未匹配字符串,进行下一次匹配
                    msg = msg.Substring(message.Length);
                    if (!String.IsNullOrEmpty(msg))
                    {
                        msgProList.AddRange(HandlerRecvdString(msg));
                    }
                }
                else
                {
                    tempMsg = msg;
                }
                return msgProList;
            }
    
            private MsgProtocol HandleMsg(string msg)
            {
                MsgProtocol msgProtocol = new TcpSocketServer.MsgProtocol();
    
                XmlDocument xml = new XmlDocument();
                xml.LoadXml(msg);
                XmlNode node = xml.DocumentElement;
                XmlNode message = node.FirstChild;// xml.SelectSingleNode("message");
    
                if(message.Attributes["type"].Value==MsgType.TEXT.ToString())
                {
                    TextProtocol text = new TcpSocketServer.TextProtocol(message.Attributes["content"].Value);
                    msgProtocol.type = MsgType.TEXT;
                    msgProtocol.textProtocol = text;
                }
                else
                {
                    FileProtocol file = new TcpSocketServer.FileProtocol(message.Attributes["content"].Value, message.Attributes["file"].Value);
                    msgProtocol.type = MsgType.FILE;
                    msgProtocol.fileProtocol = file;
                }
    
                return msgProtocol;
            }
    
        }
    }

    5)消息协议

    处理每次消息发送时粘包问题

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    
    namespace TcpSocketServer
    {
        public enum MsgType
        {
            UNKNOWN = 0,
            TEXT = 1,
            FILE = 2
        }
    
        public class TextProtocol
        {
            public string content;
    
            private MsgType type=MsgType.TEXT;
    
            public TextProtocol(string content)
            {
                this.content = content;
            }
    
            //public byte[] ToBytes()
            //{
            //    string msgPackage = ToString();
            //    return Encoding.Default.GetBytes(msgPackage);
            //}
    
            public override string ToString()
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("<message ");
                sb.Append(string.Format("type="{0}"", type.ToString()));
                sb.Append(string.Format(" content="{0}"", content));
                sb.Append("/>");
    
                return sb.ToString();
            }
        }
    
        public class FileProtocol
        {
            public string filePath;
    
            public string content;
    
            private string fileName;
    
            private MsgType type = MsgType.FILE;
    
            public FileProtocol(string content,string filePath)
            {
                this.filePath = filePath;
                this.content = content;
            }
    
            public FileProtocol(string filePath)
            {
                this.filePath = filePath;
            }
    
            public override string ToString()
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("<message ");
                sb.Append(string.Format("type="{0}"", type.ToString()));
                sb.Append(string.Format(" file="{0}"", GetFileName()));
                sb.Append(string.Format(" content="{0}"", GetFileContent()));
                sb.Append("/>");
    
                return sb.ToString();
            }
    
            public byte[] ToBytes()
            {
                return Encoding.Default.GetBytes(content);
            }
    
            private string GetFileName()
            {
                if(File.Exists(filePath))
                {
                    return Path.GetFileName(filePath);
                }
                else
                {
                    return "";
                }
            }
    
            private string GetFileContent()
            {
                if(File.Exists(filePath))
                {
                    byte[] bytes = File.ReadAllBytes(filePath);
                    content = Encoding.Default.GetString(bytes);
                }
      
                return content;
            }
        }
    
        public class MsgProtocol
        {
            //公共字段
            //public string fileName;
            public MsgType type = MsgType.UNKNOWN;
    
            public TextProtocol textProtocol;
    
            public FileProtocol fileProtocol;
    
            public MsgProtocol()
            {
    
            }
    
            public MsgProtocol(TextProtocol textProtocol)
            {
                this.type = MsgType.TEXT;
                this.textProtocol = textProtocol;
            } 
            
            public MsgProtocol(FileProtocol fileProtocol)
            {
                this.type = MsgType.FILE;
                this.fileProtocol = fileProtocol;
            }
    
            public override string ToString()
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("<protocol>");
    
                if(type==MsgType.TEXT)
                {
                    sb.Append(textProtocol.ToString());
                }
                else
                {
                    sb.Append(fileProtocol.ToString());
                }
    
                sb.Append("</protocol>");
    
                return sb.ToString();
            }
    
            public byte[] ToBytes()
            {
                return Encoding.Default.GetBytes(this.ToString());
            }
    
            //public MsgProtocol(string filePath,MsgType type)
            //{
            //    type = MsgType.FILE;
            //    this.fileName = fileName;
            //    this.file
            //}      
        }
    }

    6)主程序应用

    1、服务端

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace TcpSocketServer
    {
        class Program
        {
            private static TCPServerAsync tcpServer;
    
            static void Main(string[] args)
            {
                tcpServer = new TcpSocketServer.TCPServerAsync(8899);
    
                tcpServer.DataReceived += new EventHandler<TcpSocketServer.TCPMessageArgs>(OnDataReceived);
                tcpServer.ClientConnected += new EventHandler<TcpSocketServer.TCPMessageArgs>(OnClientConnected);
                tcpServer.ClientDisconnected += new EventHandler<TcpSocketServer.TCPMessageArgs>(OnClientDisconnected);
    
                tcpServer.Start();
                Console.ReadKey();        
            }
    
            public static void OnDataReceived(object obj,TCPMessageArgs message)
            {
                ClientInfo state = message.state;
                string sendData = "Server ";
    
                //byte[] data = state.RecvDataBuffer;
                //string strData = Encoding.Default.GetString(data);
    
                //Console.WriteLine(message.state.Datagram);
    
    
                #region 协议功能测试
                List<MsgProtocol> msgList = state.MsgList;
    
                foreach (MsgProtocol msgProtocol in msgList)
                {
                    if (msgProtocol.type == MsgType.TEXT)
                    {
                        Console.WriteLine(msgProtocol.textProtocol.content);
                        sendData += msgProtocol.textProtocol.content;
                    }
                    else
                    {
                        Console.WriteLine(msgProtocol.fileProtocol.filePath);
                        sendData += msgProtocol.fileProtocol.filePath;
                    }
    
                }
                #endregion
    
                if (message.state.Datagram=="close")
                {
                    tcpServer.Close(message.state);
                    return;
                }
    
                //数据处理后发送回客户端
                //string sendData = "Server " + message.state.Datagram;
                //byte[] sendBytes = Encoding.Default.GetBytes(sendData);
                //tcpServer.Send(state, sendBytes);
    
                #region 协议功能测试      
                MsgProtocol protocol = new TcpSocketServer.MsgProtocol(new TcpSocketServer.TextProtocol(sendData));
                tcpServer.Send(state, protocol.ToBytes());
                #endregion
            }
    
            public static void OnClientConnected(object obj, TCPMessageArgs message)
            {
                Console.WriteLine("Connect:" + message.state.ClientSocket.RemoteEndPoint.ToString());
            }
            public static void OnClientDisconnected(object obj, TCPMessageArgs message)
            {
                Console.WriteLine("Disconnect:" + message.state.ClientSocket.RemoteEndPoint.ToString());
                tcpServer.Close(message.state);
            }
        }
    }

    2、客户端调用

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Text;
    
    namespace TcpSocketClient
    {
        class Program
        {
            private static TCPClientAsync tcpclient;
            private static bool b_Connecting = true;
    
            static void Main(string[] args)
            {
                IPAddress ip = IPAddress.Parse("192.168.8.15");
                tcpclient = new TcpSocketClient.TCPClientAsync(ip, 8899);
                tcpclient.ConnectAccepted += new EventHandler<TcpSocketClient.TCPMessageArgs>(OnConnected);
                tcpclient.DataReceived += new EventHandler<TcpSocketClient.TCPMessageArgs>(OnReceived);
                tcpclient.ServerCloseLink += new EventHandler<TCPMessageArgs>(OnDisConnected);
                tcpclient.Connect();
    
                while(b_Connecting)
                {
                    string msg = Console.ReadLine();
                    if(msg=="exit")
                    {
                        tcpclient.Close();
                        //b_Connecting = false;
                        break;
                    }
    
                    if(msg=="close")
                    {
                        //tcpclient.IsConnected = false;
                    }
    
                    //byte[] data = Encoding.Default.GetBytes(msg);
                    //tcpclient.Send(data);
                    //tcpclient.Receive();
    
                    MsgProtocol msgProtocol = new TcpSocketClient.MsgProtocol(new TcpSocketClient.TextProtocol(msg));
    
                    tcpclient.Send(msgProtocol.ToBytes());
                }            
            }
    
            public static void OnConnected(object obj,TCPMessageArgs msg)
            {
                Console.WriteLine("Connected.......");
                tcpclient.Receive();
            }
    
            public static void OnReceived(object obj, TCPMessageArgs msg)
            {
                //Console.WriteLine("Receivedd "+msg.state.Datagram);
                List<MsgProtocol> msgList = msg.state.MsgList;
    
                foreach(MsgProtocol msgProtocol in msgList)
                {
                    if(msgProtocol.type==MsgType.TEXT)
                    {
                        Console.WriteLine(msgProtocol.textProtocol.content);
                    }
                    else
                    {
                        Console.WriteLine(msgProtocol.fileProtocol.filePath);
                    }
                    
                }
            }
    
            public static void OnDisConnected(object obj,TCPMessageArgs msg)
            {
                Console.WriteLine("Server Disconnected");
            }
        }
    }

    PS:未作客户端短线重连

  • 相关阅读:
    PTA 1007 Maximum Subsequence Sum (25 分)
    c++ primer 6th 函数
    redis源码笔记(持续更新)
    c文件函数总结
    PAT基础知识点
    vector模糊查询
    c++ primer 15th 面向对象程序设计
    c++ primer 18th 用于大型程序的工具
    c++ primer 19th 特殊工具与技术
    MFC TreeCtrl
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/9204966.html
Copyright © 2020-2023  润新知