C#之Socket客户端全过程

Irene ·
更新时间:2024-09-20
· 384 次阅读

目录

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# socket

需要 登录 后方可回复, 如果你还没有账号请 注册新账号