C\#.NET 에서 Socket 간단 하고 실 용적 인 프레임 워 크 사용 튜 토리 얼

21170 단어 c#.net소켓 프레임
머리말
Socket 하면 모두 가 어느 정도 관련 이 있 을 것 입 니 다.최초의 컴퓨터 네트워크 과정 에서 tcp 프로 토 콜 을 이 야 기 했 고 Socket 은 프로 토 콜 에 대한 진일보 한 패키지 로 우리 개발 자 들 이 소프트웨어 간 의 통신 을 더욱 쉽게 할 수 있 도록 합 니 다.
이번 주 에 마침 차 의 자 물 쇠 를 공유 하 는 프로젝트 를 받 았 습 니 다.Socket 과 하드웨어 를 사용 하여 통신 통 제 를 해 야 합 니 다.즉,자물쇠 에 명령 을 보 내 고 열 리 거나 닫 히 는 것 을 제어 하 는 것 입 니 다.그리고 App 에 조작 인 터 페 이 스 를 개방 하여 테스트 와 사용자 의 사용 을 편리 하 게 해 야 합 니 다.그 중에서 핵심 은 바로 Socket 의 사용 이다.이 기능 을 개발 한 후에 저 는 사용 하기에 매우 불편 하 다 는 것 을 알 게 되 었 습 니 다.그래서 2 일 동안 그 핵심 기능 을 추상 화하 고 프레임 워 크 로 포장 한 다음 에 이 프레임 워 크 를 사용 하여 원래 의 프로젝트 를 재 구성 하고 출시 하여 소프트웨어 의 확장 성,건장 성,용 착 률 을 크게 향상 시 켰 습 니 다.
개인 이 굳 게 믿 는 원칙:만물 은 모두 대상 이다.
자,잔말 말고 본문 으로 들 어가 세 요.
본문:
1.먼저 C\#중 Socket 의 간단 한 사용 에 대해 간단히 설명 합 니 다.
첫 번 째 단계:서버 에서 어떤 포트 를 감청 합 니 다.
두 번 째 단계:클 라 이언 트 가 서버 주소 와 포트 에 Socket 연결 요청 을 합 니 다.
세 번 째 단계:서버 에서 연결 요청 을 받 은 후 Socket 연결 을 만 들 고 이 연결 대기 열 을 유지 합 니 다.
네 번 째 단계:클 라 이언 트 와 서비스 사 이 드 는 쌍 공 통신(즉,양 방향 통신)을 구축 하여 클 라 이언 트 와 서비스 사 이 드 는 서로 에 게 쉽게 정 보 를 보 낼 수 있다.
간단하게 사용 하 는 구체 적 인 실현 코드 는 모두 제 가 프로젝트 에 포 장 했 습 니 다.만약 에 간단 한 실현 을 배 워 야 한다 면 제 소스 코드 를 볼 수 있 고 바 이 두 도 할 수 있 습 니 다.많은 튜 토리 얼 이 있 습 니 다.
2.핵심,프레임 의 사용
사실 틀 이 라 고 하기 에는 무리 가 있 을 수 있 습 니 다.모든 사람 이 틀 에 대해 자신 만 의 이 해 를 가지 고 있 기 때 문 입 니 다.그러나 라 이브 러 리 와 틀 은 어떤 본질 적 인 차이 가 있 습 니까?모두 코드~하하,멀 어 졌어
우선,근거 없 이 모든 코드 를 놓 습 니 다.
서버 원본 파일:
SocketServer.cs

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;

namespace Coldairarrow.Util.Sockets
{
 /// <summary>
 /// Socket   
 /// </summary>
 public class SocketServer
 {
  #region     

  /// <summary>
  ///     
  /// </summary>
  /// <param name="ip">   IP  </param>
  /// <param name="port">     </param>
  public SocketServer(string ip, int port)
  {
   _ip = ip;
   _port = port;
  }

  /// <summary>
  ///     ,  IP       0.0.0.0
  /// </summary>
  /// <param name="port">     </param>
  public SocketServer(int port)
  {
   _ip = "0.0.0.0";
   _port = port;
  }

  #endregion

  #region     

  private Socket _socket = null;
  private string _ip = "";
  private int _port = 0;
  private bool _isListen = true;
  private void StartListen()
  {
   try
   {
    _socket.BeginAccept(asyncResult =>
    {
     try
     {
      Socket newSocket = _socket.EndAccept(asyncResult);

      //         ,     
      if (_isListen)
       StartListen();

      SocketConnection newClient = new SocketConnection(newSocket, this)
      {
       HandleRecMsg = HandleRecMsg == null ? null : new Action<byte[], SocketConnection, SocketServer>(HandleRecMsg),
       HandleClientClose = HandleClientClose == null ? null : new Action<SocketConnection, SocketServer>(HandleClientClose),
       HandleSendMsg = HandleSendMsg == null ? null : new Action<byte[], SocketConnection, SocketServer>(HandleSendMsg),
       HandleException = HandleException == null ? null : new Action<Exception>(HandleException)
      };

      newClient.StartRecMsg();
      ClientList.AddLast(newClient);

      HandleNewClientConnected?.Invoke(this, newClient);
     }
     catch (Exception ex)
     {
      HandleException?.Invoke(ex);
     }
    }, null);
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
   }
  }

  #endregion

  #region     

  /// <summary>
  ///     ,     
  /// </summary>
  public void StartServer()
  {
   try
   {
    //      (ip4    ,    ,TCP  )
    _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    //  ip  
    IPAddress address = IPAddress.Parse(_ip);
    //          ip port
    IPEndPoint endpoint = new IPEndPoint(address, _port);
    //              IP   
    _socket.Bind(endpoint);
    //         Int32   (            )
    _socket.Listen(int.MaxValue);
    //       
    StartListen();
    HandleServerStarted?.Invoke(this);
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
   }
  }

  /// <summary>
  ///           
  /// </summary>
  public LinkedList<SocketConnection> ClientList { get; set; } = new LinkedList<SocketConnection>();

  /// <summary>
  ///          
  /// </summary>
  /// <param name="theClient">        </param>
  public void CloseClient(SocketConnection theClient)
  {
   theClient.Close();
  }

  #endregion

  #region     

  /// <summary>
  ///       
  /// </summary>
  public Action<Exception> HandleException { get; set; }

  #endregion

  #region      

  /// <summary>
  ///        
  /// </summary>
  public Action<SocketServer> HandleServerStarted { get; set; }

  /// <summary>
  ///           
  /// </summary>
  public Action<SocketServer, SocketConnection> HandleNewClientConnected { get; set; }

  /// <summary>
  ///            
  /// </summary>
  public Action<SocketServer, SocketConnection> HandleCloseClient { get; set; }

  #endregion

  #region        

  /// <summary>
  ///               
  /// </summary>
  public Action<byte[], SocketConnection, SocketServer> HandleRecMsg { get; set; }

  /// <summary>
  ///             
  /// </summary>
  public Action<byte[], SocketConnection, SocketServer> HandleSendMsg { get; set; }

  /// <summary>
  ///           
  /// </summary>
  public Action<SocketConnection, SocketServer> HandleClientClose { get; set; }

  #endregion
 }
}

using System;
using System.Net.Sockets;
using System.Text;

namespace Coldairarrow.Util.Sockets
{
 /// <summary>
 /// Socket  ,    
 /// </summary>
 public class SocketConnection
 {
  #region     

  public SocketConnection(Socket socket,SocketServer server)
  {
   _socket = socket;
   _server = server;
  }

  #endregion

  #region     
  
  private readonly Socket _socket;
  private bool _isRec=true;
  private SocketServer _server = null;
  private bool IsSocketConnected()
  {
   bool part1 = _socket.Poll(1000, SelectMode.SelectRead);
   bool part2 = (_socket.Available == 0);
   if (part1 && part2)
    return false;
   else
    return true;
  }

  #endregion

  #region     

  /// <summary>
  ///          
  /// </summary>
  public void StartRecMsg()
  {
   try
   {
    byte[] container = new byte[1024 * 1024 * 2];
    _socket.BeginReceive(container, 0, container.Length, SocketFlags.None, asyncResult =>
    {
     try
     {
      int length = _socket.EndReceive(asyncResult);

      //         ,     
      if (length > 0 && _isRec && IsSocketConnected())
       StartRecMsg();

      if (length > 0)
      {
       byte[] recBytes = new byte[length];
       Array.Copy(container, 0, recBytes, 0, length);

       //    
       HandleRecMsg?.Invoke(recBytes, this, _server);
      }
      else
       Close();
     }
     catch (Exception ex)
     {
      HandleException?.Invoke(ex);
      Close();
     }
    }, null);
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
    Close();
   }
  }

  /// <summary>
  ///     
  /// </summary>
  /// <param name="bytes">    </param>
  public void Send(byte[] bytes)
  {
   try
   {
    _socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, asyncResult =>
    {
     try
     {
      int length = _socket.EndSend(asyncResult);
      HandleSendMsg?.Invoke(bytes, this, _server);
     }
     catch (Exception ex)
     {
      HandleException?.Invoke(ex);
     }
    }, null);
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
   }
  }

  /// <summary>
  ///      (    UTF-8  )
  /// </summary>
  /// <param name="msgStr">   </param>
  public void Send(string msgStr)
  {
   Send(Encoding.UTF8.GetBytes(msgStr));
  }

  /// <summary>
  ///      (       )
  /// </summary>
  /// <param name="msgStr">     </param>
  /// <param name="encoding">     </param>
  public void Send(string msgStr,Encoding encoding)
  {
   Send(encoding.GetBytes(msgStr));
  }

  /// <summary>
  ///        
  /// </summary>
  public object Property { get; set; }

  /// <summary>
  ///       
  /// </summary>
  public void Close()
  {
   try
   {
    _isRec = false;
    _socket.Disconnect(false);
    _server.ClientList.Remove(this);
    HandleClientClose?.Invoke(this, _server);
    _socket.Close();
    _socket.Dispose();
    GC.Collect();
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
   }
  }

  #endregion

  #region     

  /// <summary>
  ///               
  /// </summary>
  public Action<byte[], SocketConnection, SocketServer> HandleRecMsg { get; set; }

  /// <summary>
  ///             
  /// </summary>
  public Action<byte[], SocketConnection, SocketServer> HandleSendMsg { get; set; }

  /// <summary>
  ///           
  /// </summary>
  public Action<SocketConnection, SocketServer> HandleClientClose { get; set; }

  /// <summary>
  ///       
  /// </summary>
  public Action<Exception> HandleException { get; set; }

  #endregion
 }
}

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Coldairarrow.Util.Sockets
{
 /// <summary>
 /// Socket   
 /// </summary>
 public class SocketClient
 {
  #region     

  /// <summary>
  ///     ,     IP       127.0.0.1
  /// </summary>
  /// <param name="port">     </param>
  public SocketClient(int port)
  {
   _ip = "127.0.0.1";
   _port = port;
  }

  /// <summary>
  ///     
  /// </summary>
  /// <param name="ip">   IP  </param>
  /// <param name="port">     </param>
  public SocketClient(string ip, int port)
  {
   _ip = ip;
   _port = port;
  }

  #endregion

  #region     

  private Socket _socket = null;
  private string _ip = "";
  private int _port = 0;
  private bool _isRec=true;
  private bool IsSocketConnected()
  {
   bool part1 = _socket.Poll(1000, SelectMode.SelectRead);
   bool part2 = (_socket.Available == 0);
   if (part1 && part2)
    return false;
   else
    return true;
  }

  /// <summary>
  ///          
  /// </summary>
  public void StartRecMsg()
  {
   try
   {
    byte[] container = new byte[1024 * 1024 * 2];
    _socket.BeginReceive(container, 0, container.Length, SocketFlags.None, asyncResult =>
    {
     try
     {
      int length = _socket.EndReceive(asyncResult);

      //         ,     
      if (length > 0 && _isRec && IsSocketConnected())
       StartRecMsg();

      if (length > 0)
      {
       byte[] recBytes = new byte[length];
       Array.Copy(container, 0, recBytes, 0, length);

       //    
       HandleRecMsg?.Invoke(recBytes, this);
      }
      else
       Close();
     }
     catch (Exception ex)
     {
      HandleException?.Invoke(ex);
      Close();
     }
    }, null);
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
    Close();
   }
  }

  #endregion

  #region     

  /// <summary>
  ///     ,     
  /// </summary>
  public void StartClient()
  {
   try
   {
    //        (ip4    ,    ,TCP  )
    _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    //   ip  
    IPAddress address = IPAddress.Parse(_ip);
    //            ip port
    IPEndPoint endpoint = new IPEndPoint(address, _port);
    //               IP   
    _socket.BeginConnect(endpoint, asyncResult =>
    {
     try
     {
      _socket.EndConnect(asyncResult);
      //         
      StartRecMsg();

      HandleClientStarted?.Invoke(this);
     }
     catch (Exception ex)
     {
      HandleException?.Invoke(ex);
     }
    }, null);
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
   }
  }

  /// <summary>
  ///     
  /// </summary>
  /// <param name="bytes">    </param>
  public void Send(byte[] bytes)
  {
   try
   {
    _socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, asyncResult =>
    {
     try
     {
      int length = _socket.EndSend(asyncResult);
      HandleSendMsg?.Invoke(bytes, this);
     }
     catch (Exception ex)
     {
      HandleException?.Invoke(ex);
     }
    }, null);
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
   }
  }

  /// <summary>
  ///      (    UTF-8  )
  /// </summary>
  /// <param name="msgStr">   </param>
  public void Send(string msgStr)
  {
   Send(Encoding.UTF8.GetBytes(msgStr));
  }

  /// <summary>
  ///      (       )
  /// </summary>
  /// <param name="msgStr">     </param>
  /// <param name="encoding">     </param>
  public void Send(string msgStr, Encoding encoding)
  {
   Send(encoding.GetBytes(msgStr));
  }

  /// <summary>
  ///        
  /// </summary>
  public object Property { get; set; }

  /// <summary>
  ///          
  /// </summary>
  public void Close()
  {
   try
   {
    _isRec = false;
    _socket.Disconnect(false);
    HandleClientClose?.Invoke(this);
   }
   catch (Exception ex)
   {
    HandleException?.Invoke(ex);
   }
  }

  #endregion

  #region     

  /// <summary>
  ///           
  /// </summary>
  public Action<SocketClient> HandleClientStarted { get; set; }

  /// <summary>
  ///          
  /// </summary>
  public Action<byte[], SocketClient> HandleRecMsg { get; set; }

  /// <summary>
  ///             
  /// </summary>
  public Action<byte[], SocketClient> HandleSendMsg { get; set; }

  /// <summary>
  ///           
  /// </summary>
  public Action<SocketClient> HandleClientClose { get; set; }

  /// <summary>
  ///       
  /// </summary>
  public Action<Exception> HandleException { get; set; }

  #endregion
 }
}
위 에 놓 인 것 은 프레임 코드 입 니 다.다음은 어떻게 사용 하 는 지 소개 하 겠 습 니 다.
우선,서버 사용 방식:

using Coldairarrow.Util.Sockets;
using System;
using System.Text;

namespace Console_Server
{
 class Program
 {
  static void Main(string[] args)
  {
   //       ,      0.0.0.0,  12345
   SocketServer server = new SocketServer(12345);

   //           
   server.HandleRecMsg = new Action<byte[], SocketConnection, SocketServer>((bytes, client, theServer) =>
   {
    string msg = Encoding.UTF8.GetString(bytes);
    Console.WriteLine($"    :{msg}");
   });

   //          
   server.HandleServerStarted = new Action<SocketServer>(theServer =>
   {
    Console.WriteLine("     ************");
   });

   //             
   server.HandleNewClientConnected = new Action<SocketServer, SocketConnection>((theServer, theCon) =>
   {
    Console.WriteLine($@"         ,     :{theServer.ClientList.Count}");
   });

   //             
   server.HandleClientClose = new Action<SocketConnection, SocketServer>((theCon, theServer) =>
   {
    Console.WriteLine($@"       ,      :{theServer.ClientList.Count}");
   });

   //    
   server.HandleException = new Action<Exception>(ex =>
   {
    Console.WriteLine(ex.Message);
   });

   //     
   server.StartServer();

   while (true)
   {
    Console.WriteLine("  :quit,     ");
    string op = Console.ReadLine();
    if (op == "quit")
     break;
   }
  }
 }
}
클 라 이언 트 사용 방법:

using Coldairarrow.Util.Sockets;
using System;
using System.Text;

namespace Console_Client
{
 class Program
 {
  static void Main(string[] args)
  {
   //       ,      127.0.0.1,   12345
   SocketClient client = new SocketClient(12345);

   //                   
   client.HandleRecMsg = new Action<byte[], SocketClient>((bytes, theClient) =>
   {
    string msg = Encoding.UTF8.GetString(bytes);
    Console.WriteLine($"    :{msg}");
   });

   //                
   client.HandleSendMsg = new Action<byte[], SocketClient>((bytes, theClient) =>
   {
    string msg = Encoding.UTF8.GetString(bytes);
    Console.WriteLine($"        :{msg}");
   });

   //       
   client.StartClient();

   while (true)
   {
    Console.WriteLine("  :quit     ,            ");
    string str = Console.ReadLine();
    if (str == "quit")
    {
     client.Close();
     break;
    }
    else
    {
     client.Send(str);
    }
   }
  }
 }
}
마지막 으로 테스트 캡 처 실행:

요약:
가장 편리 한 점 은 연결 패 키 징 을 만 드 는 방법 입 니 다.사용 자 는 연결 후 어떤 데 이 터 를 보 내 는 지,데 이 터 를 받 은 후에 어떻게 처리 해 야 하 는 지 등 다른 많은 사건 의 처 리 를 주목 해 야 합 니 다.그 중에서 익명 의뢰 의 사용,Lambda 표현 식 의 사용 에 의존 합 니 다.
프레임 안에 주로 비동기 통신 을 사 용 했 고 연결 을 어떻게 통제 하 는 지 상세 하 게 말씀 드 리 지 않 겠 습 니 다.여러분 들 은 한 번 보면 알 수 있 을 것 입 니 다.저 는 여러분 에 게 편 의 를 가 져 다 주 고 싶 을 뿐 입 니 다.
자,이상 이 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
마지막 으로 모든 소스 항목 주 소 를 동봉 합 니 다.어느 정도 가치 가 있다 고 생각 되면 좋아요 도 눌 러 주세요~
GitHub 주소:https://github.com/Coldairarrow/Sockets
로 컬 다운로드:http://xiazai.jb51.net/201709/yuanma/Sockets(jb51.net).rar

좋은 웹페이지 즐겨찾기