当前位置 : 主页 > 网络编程 > c#编程 >

C#之Socket客户端全过程

来源:互联网 收集:自由互联 发布时间:2023-05-16
目录 C#开发Socket客户端 C#Socket客户端异步实现 简易封装 使用 未实现的几个常用操作 总结 C#开发Socket客户端 我们先新建一个类:SocketClientAsync。 注意点: 1、由于Socket通讯是发送到缓存
目录
  • C#开发Socket客户端
  • C#Socket客户端异步实现
    • 简易封装
    • 使用
    • 未实现的几个常用操作
  • 总结

    C#开发Socket客户端

    我们先新建一个类:SocketClientAsync。

    注意点:

    1、由于Socket通讯是发送到缓存区内的数据是覆盖,而不是新的,也就是说如果我们第一次发送的内容是 byte[]{0x11,0x22};而第二次发送的内容是byte[]{0x22}。那么我们的服务端在第二次接受到的数据是byte[]{0x22,0x22}。

    所以我们需要在Socket.Send(byte[] mes)方法里面声明

    byte[] buffer = new byte[1024];
    for (int i = 0; i < buffer.Length; i++)
     {
            buffer[i] = 0x00;
    }

    起到的作用就是每次在发送新的内容到服务端的时候,会将所有的旧的内容替换掉;

    2、关闭连接之前需要将通知服务端停止发送和接受,也就是

    this.clientSocket.Shutdown(SocketShutdown.Both);

    中断套接字连接:通知服务器端或客户端停止接收和发送数据。

    通知完成之后如果客户端还连接着再进行自己的连接断开

    if (this.clientSocket.Connected)
     {
             this.clientSocket.Close();
    }

    3、具体类的代码见下图,可以直接使用

        #region SocketClient客户端
        public class SocketClientAsync
        {
            #region 声明变量
            public string IPAdress;
            public bool connected = false;
            public Socket clientSocket;
            private IPEndPoint hostEndPoint;
            private int Flag = 0;
            private AutoResetEvent autoConnectEvent = new AutoResetEvent(false);
            private SocketAsyncEventArgs lisnterSocketAsyncEventArgs;
            public delegate void StartListeHandler();
            public event StartListeHandler StartListen;
            public delegate void ReceiveMsgHandler(byte[] info, int i);
            public event ReceiveMsgHandler OnMsgReceived;
            private List<SocketAsyncEventArgs> s_lst = new List<SocketAsyncEventArgs>();
            #endregion
            #region 构造函数
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="hostName"></param>
            /// <param name="port"></param>
            /// <param name="i"></param>
            public SocketClientAsync(string hostName, int port, int i)
            {
                Flag = i;
                IPAdress = hostName;
                IPAddress[] hostAddresses = Dns.GetHostAddresses(hostName);
                this.hostEndPoint = new IPEndPoint(hostAddresses[hostAddresses.Length - 1], port);
                this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            }
            #endregion
            #region 开始连接服务端
            /// <summary>
            /// 连接服务端
            /// </summary>
            /// <returns></returns>
            private bool Connect()
            {
                using (SocketAsyncEventArgs args = new SocketAsyncEventArgs())
                {
                    args.UserToken = this.clientSocket;
                    args.RemoteEndPoint = this.hostEndPoint;
                    args.Completed += new EventHandler<SocketAsyncEventArgs>(this.OnConnect);
                    this.clientSocket.ConnectAsync(args);
                    bool flag = autoConnectEvent.WaitOne(5000);
                    if (this.connected)
                    {
                        this.lisnterSocketAsyncEventArgs = new SocketAsyncEventArgs();
                        byte[] buffer = new byte[1024];
                        this.lisnterSocketAsyncEventArgs.UserToken = this.clientSocket;
                        this.lisnterSocketAsyncEventArgs.SetBuffer(buffer, 0, buffer.Length);
                        this.lisnterSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(this.OnReceive);
                        this.StartListen();
                        return true;
                    }
                    return false;
                }
            }
            #endregion
            #region 判断有没有连接上服务端
            /// <summary>
            /// 判断有没有连接上
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnConnect(object sender, SocketAsyncEventArgs e)
            {
                this.connected = (e.SocketError == SocketError.Success);
                autoConnectEvent.Set();
            }
            #endregion
            #region 发送数据到服务端
            /// <summary>
            /// 发送
            /// </summary>
            /// <param name="mes"></param>
            public void Send(byte[] mes)
            {
                if (this.connected)
                {
                    EventHandler<SocketAsyncEventArgs> handler = null;
                    //byte[] buffer = Encoding.Default.GetBytes(mes);
                    byte[] buffer = new byte[1024];
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        buffer[i] = 0x00;
                    }
                    Array.Copy(mes, 0, buffer, 0, mes.Length);
                    SocketAsyncEventArgs senderSocketAsyncEventArgs = null;
                    lock (s_lst)
                    {
                        if (s_lst.Count > 0)
                        {
                            senderSocketAsyncEventArgs = s_lst[s_lst.Count - 1];
                            s_lst.RemoveAt(s_lst.Count - 1);
                        }
                    }
                    if (senderSocketAsyncEventArgs == null)
                    {
                        senderSocketAsyncEventArgs = new SocketAsyncEventArgs();
                        senderSocketAsyncEventArgs.UserToken = this.clientSocket;
                        senderSocketAsyncEventArgs.RemoteEndPoint = this.clientSocket.RemoteEndPoint;
                        if (handler == null)
                        {
                            handler = delegate(object sender, SocketAsyncEventArgs _e)
                            {
                                lock (s_lst)
                                {
                                    s_lst.Add(senderSocketAsyncEventArgs);
                                }
                            };
                        }
                        senderSocketAsyncEventArgs.Completed += handler;
                    }
                    senderSocketAsyncEventArgs.SetBuffer(buffer, 0, buffer.Length);
                    this.clientSocket.SendAsync(senderSocketAsyncEventArgs);
                }
                else
                {
                    this.connected = false;
                }
            }
            #endregion
            #region 监听服务端
            /// <summary>
            /// 监听服务端
            /// </summary>
            public void Listen()
            {
                if (this.connected && this.clientSocket != null)
                {
                    try
                    {
                        (lisnterSocketAsyncEventArgs.UserToken as Socket).ReceiveAsync(lisnterSocketAsyncEventArgs);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
            #endregion
            #region 断开服务端的连接
            /// <summary>
            /// 断开连接
            /// </summary>
            /// <returns></returns>
            private int Disconnect()
            {
                int res = 0;
                try
                {
                    this.clientSocket.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                }
                try
                {
                    this.clientSocket.Close();
                }
                catch (Exception)
                {
                }
                this.connected = false;
                return res;
            }
            #endregion
            #region 数据接收
            /// <summary>
            /// 数据接受
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnReceive(object sender, SocketAsyncEventArgs e)
            {
                if (e.BytesTransferred == 0)
                {
                    if (clientSocket.Connected)
                    {
                        try
                        {
                            this.clientSocket.Shutdown(SocketShutdown.Both);
                        }
                        catch (Exception)
                        {
                        }
                        finally
                        {
                            if (this.clientSocket.Connected)
                            {
                                this.clientSocket.Close();
                            }
                        }
                    }
                    byte[] info = new Byte[] { 0 };
                    this.OnMsgReceived(info, Flag);
                }
                else
                {
                    byte[] buffer = new byte[e.BytesTransferred];
                    Buffer.BlockCopy(e.Buffer, 0, buffer, 0, e.BytesTransferred);
                    this.OnMsgReceived(buffer, Flag);
                    Listen();
                }
            }
            #endregion
            #region 建立连接服务端的方法
            /// <summary>
            /// 建立连接的方法
            /// </summary>
            /// <returns></returns>
            public bool ConnectServer()
            {
                bool flag = false;
                this.StartListen += new StartListeHandler(SocketClient_StartListen);
                // this.OnMsgReceived += new ReceiveMsgHandler(SocketClient_OnMsgReceived);
                flag = this.Connect();
                if (!flag)
                {
                    return flag;
                }
                return true;
            }
            #endregion
            #region 关闭与服务端之间的连接
            /// <summary>
            /// 关闭连接的方法
            /// </summary>
            /// <returns></returns>
            public int CloseLinkServer()
            {
                return this.Disconnect();
            }
            #endregion
            #region 监听方法
            /// <summary>
            /// 监听的方法
            /// </summary>
            private void SocketClient_StartListen()
            {
                this.Listen();
            }
            #endregion
            #region IDispose member
            public void Dispose()
            {
                if (this.clientSocket.Connected)
                {
                    this.clientSocket.Close();
                }
            }
            #endregion
            #region 析构函数
            ~SocketClientAsync()
            {
                try
                {
                    if (this.clientSocket.Connected)
                    {
                        this.clientSocket.Close();
                    }
                }
                catch
                {
                }
                finally
                {
                }
            }
            #endregion
        }
        #endregion

    4、然后就是类的调用了

            //声明定义变量
            private SocketClientAsync ClientLink;//客户端连接对象
            private string Client_IP = "127.0.0.1";//服务端IP地址
            private int Client_Port = 12345;//服务端监听的端口号
            private Thread Client_Td;//通讯内部使用线程
            private bool ClientLinkRes = false;//服务器通讯状态标志
            private bool ThreadContinue = true;//线程轮询标志
            private bool isOnline = false;//是否在线标志
            /// <summary>
            /// 启动线程
            /// </summary>
            private void StartServer()
            {
                Client_Td = new Thread(LinkSocketSerFunc);
                Client_Td.Start();
            }
            /// <summary>
            /// 重连服务端线程
            /// </summary>
            private void LinkSocketSerFunc()
            {
                object lockobj = new object();
                int heartBeatCount = 0;
                ClientLink = new SocketClientAsync(Client_IP, Client_Port, 0);
                bool NotFirstIn = false;
                while (ThreadContinue)
                {
                    try
                    {
                        if (!ClientLinkRes)
                        {
                            isOnline = false;
                            if (NotFirstIn)
                            {
                                ClientLink.CloseLinkServer();
                                ClientLink = new SocketClientAsync(Client_IP, Client_Port, 0);
                            }
                            NotFirstIn = true;
                            ClientLink.OnMsgReceived += new SocketClientAsync.ReceiveMsgHandler(Client_OnMsgReceived);//绑定接受到服务端消息的事件
                            ClientLinkRes = ClientLink.ConnectServer();
                        }
                        else
                        {
                            //此处写通讯成功的逻辑处理
                        }
                    }
                    catch (Exception ex)
                    {
                        ClientLinkRes = false;
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
                    }
                    Thread.Sleep(1000);
                }
            }
            /// <summary>
            /// 接收消息处理
            /// </summary>
            /// <param name="info"></param>
            /// <param name="num"></param>
            private void Client_OnMsgReceived(byte[] info, int num)
            {
                try
                {
                    ClientHeartBeat = 0;
                    if (info.Length > 0 && info[0] != 0)//BCR连接错误NO
                    {
                        //info为接受到服务器传过来的字节数组,需要进行什么样的逻辑处理在此书写便可                        
                    }
                    else
                    {
                        ClientLinkRes = false;
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.ToString());
                }
            }
            /// <summary>
            /// 终止服务
            /// </summary>
            public void StopServer()
            {
                if (ClientLinkRes)
                {
                    ThreadContinue = false;
                    ClientLink.CloseLinkServer();
                    ClientLink.Dispose();
                }
            }

    这基本的Socket客户端后台就写完了,可以直接复制使用,平时都是用这么去写Socket客户端,分享出来,大家就可以直接使用了!

    C#Socket客户端异步实现

    简易封装

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Net;
    using System.Net.Sockets;
    namespace dclient
    {
        public delegate void DelegateMsg(object msg);
        public class Client
        {
            private static Socket _clientSocket;
            private static string _server;
            private static int _port;
            public static DelegateMsg OnConnect;
            public static DelegateMsg OnSend;
            public static DelegateMsg OnReceive;
            public static DelegateMsg OnServerDown;
            public static DelegateMsg OnErr;
            public static void Connect()
            {
                try
                {
                    _server = System.Configuration.ConfigurationManager.AppSettings["serverIp"];
                    _port = int.Parse(System.Configuration.ConfigurationManager.AppSettings["serverPort"]);
                    IPEndPoint ip = new IPEndPoint(IPAddress.Parse(_server), _port);
                    _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    _clientSocket.BeginConnect(ip, new AsyncCallback(ConnectCallBack), _clientSocket);
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
            private static void ConnectCallBack(IAsyncResult iar)
            {
                Socket client = (Socket)iar.AsyncState;
                try
                {
                    client.EndConnect(iar);
                    OnConnect("已连接");
                }
                catch (SocketException e)
                {
                    if (e.ErrorCode == 10061)
                    {
                        OnErr("服务器程序未运行或服务器端口未开放");
                    }
                    else
                    {
                        OnErr(e.Message);
                    }
                }
                finally
                {
                }
            }
            public static void Send(string msg)
            {
                if (_clientSocket == null || msg == string.Empty) return;
                msg += "\r\n";
                byte[] data = Encoding.UTF8.GetBytes(msg);
                try
                {
                    _clientSocket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
                    {
                        int length = _clientSocket.EndSend(asyncResult);
                        OnSend(string.Format("客户端发送消息:{0}", msg));
                    }, null);
                }
                catch (Exception e)
                {
                    OnErr(e.Message);
                }
            }
            public static void Recive()
            {
                byte[] data = new byte[1024];
                try
                {
                    _clientSocket.BeginReceive(data, 0, data.Length, SocketFlags.None,
                    asyncResult =>
                    {
                        try
                        {
                            int length = _clientSocket.EndReceive(asyncResult);
                            OnReceive(string.Format("收到服务器消息:长度:{1},{0}", Encoding.UTF8.GetString(data), length));
                            Recive();
                        }
                        catch (SocketException e)
                        {
                            if (e.ErrorCode == 10054)
                            {
                                OnServerDown("服务器已断线");
                            }
                            else
                            {
                                OnErr(e.Message);
                            }
                        }
                    }, null);
                }
                catch (Exception ex)
                {
                    OnErr(ex.Message);
                }
            }
        }
    }

    使用

      public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                Client.OnConnect += new DelegateMsg(connect);
                Client.OnSend += new DelegateMsg(send);
                Client.OnReceive += new DelegateMsg(receive);
                Client.OnServerDown += new DelegateMsg(svrdown);
                Client.OnErr += new DelegateMsg(onerr);
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                Client.Connect();
            }
            private void connect(object msg)
            {
                System.Diagnostics.Debug.WriteLine(msg.ToString());
                Client.Send("DALO 发送测试");
                Client.Recive();
            }
            private void send(object msg)
            {
                System.Diagnostics.Debug.WriteLine(msg.ToString());
            }
            private void receive(object msg)
            {
                System.Diagnostics.Debug.WriteLine(msg.ToString());
            }
            private void svrdown(object msg)
            {
                System.Diagnostics.Debug.WriteLine(msg.ToString());
            }
            private void onerr(object msg)
            {
                System.Diagnostics.Debug.WriteLine(msg.ToString());
            }
        }

    未实现的几个常用操作

    1、接收服务器发送的大数据量的合包。

    2、服务器断线后客户端自动检测并重连,需先将_clientSocket释放。

    3、心跳包。

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

    上一篇:C#实现文件筛选读取并翻译的自动化工具
    下一篇:没有了
    网友评论