开发者

C#之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.lisnterSocketAsyncEv开发者_JS学习entArgs.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()
        js{
          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 NpythonotFirstIn = 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.ApythonppSettings["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、心跳包。

    总结

    以上为个人经验,希望能给大家一个参www.devze.com考,也希望大家多多支持我们。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜