C#基于Socket套接字的网络通信封装
作者:uiuan00 发布时间:2023-11-08 16:42:18
标签:C#,套接字,网络通信
本文为大家分享了C#基于Socket套接字的网络通信封装代码,供大家参考,具体内容如下
摘要
之所以要进行Socket套接字通信库封装,主要是直接使用套接字进行网络通信编程相对复杂,特别对于初学者而言。实际上微软从.net 2.0开始已经提供了TCP、UDP通信高级封装类如下:
TcpListener
TcpClient
UdpClient
微软从.net 4.0开始提供基于Task任务的异步通信接口。而直接使用socket封装库,很多socket本身的细节没办法自行控制,本文目就是提供一种socket的封装供参考。文中展示部分封装了TCP通信库,UDP封装也可触类旁通:
CusTcpListener
CusTcpClient
TCP服务端
TCP服务端封装了服务端本地绑定、监听、接受客户端连接,并提供了网络数据流的接口。完整代码:
public class CusTcpListener
{
private IPEndPoint mServerSocketEndPoint;
private Socket mServerSocket;
private bool isActive;
public Socket Server
{
get { return this.mServerSocket; }
}
protected bool Active
{
get { return this.isActive; }
}
public EndPoint LocalEndpoint
{
get
{
if (!this.isActive)
{
return this.mServerSocketEndPoint;
}
return this.mServerSocket.LocalEndPoint;
}
}
public NetworkStream DataStream
{
get
{
NetworkStream networkStream = null;
if (this.Server.Connected)
{
networkStream = new NetworkStream(this.Server, true);
}
return networkStream;
}
}
public CusTcpListener(IPEndPoint localEP)
{
this.mServerSocketEndPoint = localEP;
this.mServerSocket = new Socket(this.mServerSocketEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
public CusTcpListener(string localaddr, int port)
{
if (localaddr == null)
{
throw new ArgumentNullException("localaddr");
}
this.mServerSocketEndPoint = new IPEndPoint(IPAddress.Parse(localaddr), port);
this.mServerSocket = new Socket(this.mServerSocketEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
public CusTcpListener(int port)
{
this.mServerSocketEndPoint = new IPEndPoint(IPAddress.Any, port);
this.mServerSocket = new Socket(this.mServerSocketEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
public void Start()
{
this.Start(int.MaxValue);
}
/// <summary>
/// 开始服务器监听
/// </summary>
/// <param name="backlog">同时等待连接的最大个数(半连接队列个数限制)</param>
public void Start(int backlog)
{
if (backlog > int.MaxValue || backlog < 0)
{
throw new ArgumentOutOfRangeException("backlog");
}
if (this.mServerSocket == null)
{
throw new NullReferenceException("套接字为空");
}
this.mServerSocket.Bind(this.mServerSocketEndPoint);
this.mServerSocket.Listen(backlog);
this.isActive = true;
}
public void Stop()
{
if (this.mServerSocket != null)
{
this.mServerSocket.Close();
this.mServerSocket = null;
}
this.isActive = false;
this.mServerSocket = new Socket(this.mServerSocketEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
public Socket AcceptSocket()
{
Socket socket = this.mServerSocket.Accept();
return socket;
}
public CusTcpClient AcceptTcpClient()
{
CusTcpClient tcpClient = new CusTcpClient(this.mServerSocket.Accept());
return tcpClient;
}
}
TCP客户端
TCP客户端封装了客户端本地绑定、连接服务器,并提供了网络数据流的接口。完整代码:
public class CusTcpClient : IDisposable
{
public Socket Client { get; set; }
protected bool Active { get; set; }
public IPEndPoint ClientSocketEndPoint { get; set; }
public bool IsConnected { get { return this.Client.Connected; } }
public NetworkStream DataStream
{
get
{
NetworkStream networkStream = null;
if (this.Client.Connected)
{
networkStream = new NetworkStream(this.Client, true);
}
return networkStream;
}
}
public CusTcpClient(IPEndPoint localEP)
{
if (localEP == null)
{
throw new ArgumentNullException("localEP");
}
this.Client = new Socket(localEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.Active = false;
this.Client.Bind(localEP);
this.ClientSocketEndPoint = localEP;
}
public CusTcpClient(string localaddr, int port)
{
if (localaddr == null)
{
throw new ArgumentNullException("localaddr");
}
IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(localaddr), port);
this.Client = new Socket(localEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.Active = false;
this.Client.Bind(localEP);
this.ClientSocketEndPoint = localEP;
}
internal CusTcpClient(Socket acceptedSocket)
{
this.Client = acceptedSocket;
this.Active = true;
this.ClientSocketEndPoint = (IPEndPoint)this.Client.LocalEndPoint;
}
public void Connect(string address, int port)
{
if (address == null)
{
throw new ArgumentNullException("address");
}
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(address), port);
this.Connect(remoteEP);
}
public void Connect(IPEndPoint remoteEP)
{
if (remoteEP == null)
{
throw new ArgumentNullException("remoteEP");
}
this.Client.Connect(remoteEP);
this.Active = true;
}
public void Close()
{
this.Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
IDisposable dataStream = this.DataStream;
if (dataStream != null)
{
dataStream.Dispose();
}
else
{
Socket client = this.Client;
if (client != null)
{
client.Close();
this.Client = null;
}
}
GC.SuppressFinalize(this);
}
}
public void Dispose()
{
this.Dispose(true);
}
}
通信实验
控制台程序试验,服务端程序:
class Program
{
static void Main(string[] args)
{
Thread listenerThread = new Thread(ListenerClientConnection);
listenerThread.IsBackground = true;
listenerThread.Start();
Console.ReadKey();
}
private static void ListenerClientConnection()
{
CusTcpListener tcpListener = new CusTcpListener("127.0.0.1", 5100);
tcpListener.Start();
Console.WriteLine("等待客户端连接……");
while (true)
{
CusTcpClient tcpClient = tcpListener.AcceptTcpClient();
Console.WriteLine("客户端接入,ip={0} port={1}",
tcpClient.ClientSocketEndPoint.Address, tcpClient.ClientSocketEndPoint.Port);
Thread thread = new Thread(DataHandleProcess);
thread.IsBackground = true;
thread.Start(tcpClient);
}
}
private static void DataHandleProcess(object obj)
{
CusTcpClient tcpClient = (CusTcpClient)obj;
StreamReader streamReader = new StreamReader(tcpClient.DataStream, Encoding.Default);
Console.WriteLine("等待客户端输入:");
while (true)
{
try
{
string receStr = streamReader.ReadLine();
Console.WriteLine(receStr);
}
catch (Exception)
{
Console.WriteLine("断开连接");
break;
}
Thread.Sleep(5);
}
}
}
客户端程序:
class Program
{
static void Main(string[] args)
{
Thread listenerThread = new Thread(UserProcess);
listenerThread.IsBackground = true;
listenerThread.Start();
Console.ReadKey();
}
private static void UserProcess()
{
Console.WriteLine("连接服务器");
CusTcpClient tcpClient = new CusTcpClient("127.0.0.1", 5080);
tcpClient.Connect("127.0.0.1", 5100);
Console.WriteLine("开始和服务器通信");
StreamWriter sw = new StreamWriter(tcpClient.DataStream, Encoding.Default);
sw.AutoFlush = true;
while (true)
{
for (int i = 0; i < 10; i++)
{
string str = string.Format("第{0}次,内容:{1}", i, "测试通信");
Console.WriteLine("发送数据:{0}", str);
sw.WriteLine(str);
}
break;
}
}
}
通信成功:
通过本次封装演示可实现基于Socket的通信库封装,目的就是使用Socket通信库让应用开发人员在进行网络通讯编程时无需关心底层通讯机制,而只关心应用层的开发,让开发变得更简洁。当然UDP封装类似,可自行设计。当然本文只是一种示例,实际使用可使用.net自带封装库或自定义封装。
补充:目前有很多优秀的开源Socket框架,比如SuperSocket、FastSocket等。
来源:https://blog.csdn.net/uiuan00/article/details/39580787


猜你喜欢
- Gituhb项目Volley源码中文注释项目我已经上传到github,欢迎大家fork和start.为什么写这篇博客本来文章是维护在gith
- 谈到多线程就不得不谈到Synchronized,重要性不言而喻,今天主要谈谈Synchronized的实现原理。Synchronizedsy
- C#生成指定范围内的不重复随机数// Number随机数个数// minNum随机数下限// maxNum随机数上限public int[]
- 前言因为工作原因,需要在项目中集成dubbo,所以去查询dubbo相关文档,发现dubbo目前已经不更新了,所以把目光投向了dubbox,d
- eclipse的代码提交到git,下载后用新的ide工具IJ 进行开发一、导入项目eclipse里有workSpace 但是在IDEA中没有
- 1.默认的静态资源目录/static/public/resources/META-INF/resources动态资源目录:/template
- 发现公司集成apollo后原来的@value注入的属性不用做任何变动,也没有换成apollo的注解,遂略看源码后大致了解,做此笔记1、根据文
- 做Java的面试题时遇到了以下这题,百度了一下Math.round()的修约规则,有的说是四舍五入,有的说是四舍六入,发现和我学分析化学时用
- 在项目中,有时候会用到领域枚举和DTO枚举的映射和转换。有一个现实的问题是:如果领域枚举项发生变化,而DTO枚举项没有及时更新,这样会造成映
- 一、return语句执行顺序finally语句是在return语句执行之后,return语句返回之前执行的package exception
- 本文实例讲述了C#使用listView增删操作的方法。分享给大家供大家参考。具体分析如下:应用场景: C#中使用listView控件,实现动
- 1.什么是串口?在不会使用串口通讯之前,暂且可以把它理解为“一个可通讯的口”;使用篇不深入探讨理论及
- 简介基于springboot,mybatis plus集成了一套多数据源的解决方案,在使用时引入相应的插件dynamic-datasourc
- 一、@Configuration1.1 未加@Configuration<!--logback-test.xml,配置不打印日志--&
- 前言P6Spy是一个框架,它可以无缝地拦截和记录数据库活动,而无需更改现有应用程序的代码。一般我们使用的比较多的是使用p6spy打印我们最后
- Spring BeanPostProcessor执行顺序首先 Spring 通过调用构造方法创建 User 对象;User 对象创建好之后,
- [LeetCode] 159. Longest Substring with At Most Two Distinct Characters
- 1、汉字转十六进制UNICODE编码字符串 /// <summary> /// //// /// <
- import java.util.Calendar;import java.util.Date;public class Matrix {&
- 前言大家或许在iOS程序开发中经常遇到屏幕旋转问题,比如说希望指定的页面进行不同的屏幕旋转,但由于系统提供的方法是导航控制器的全局方法,无法