服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# .NET中Socket简单实用框架的使用教程

C# .NET中Socket简单实用框架的使用教程

2022-01-21 14:02寒空飞箭 C#

最近一个项目因为要用到Socket传输问题,所以决定学习一下,将自己学习的内容总结分享出来,下面这篇文章主要给大家介绍了关于C# .NET中Socket简单实用框架使用的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参

前言

一说到socket,想必大家都或多或少有所涉及,从最初的计算机网络课程,讲述了tcp协议,而socket就是对协议的进一步封装,使我们开发人员能够更加容易轻松的进行软件之间的通信。

这个星期刚好接受一个共享车位锁的项目,需要使用socket与硬件进行通信控制,说白了也就是给锁发送指令,控制其打开或者关闭,再就是对app开放操作接口,使其方便测试以及用户的使用。这其中核心就是socket的使用,再开发出这个功能之后,我发现使用起来很不方便,于是耗时2天抽象其核心功能并封装成框架,最后使用这个框架将原来的项目重构并上线,极大的提高了软件的可拓展性,健壮性,容错率。

个人坚信的原则:万物皆对象

好了,不废话了,下面进入正文

正文:

1、首先简单讲下c#中socket的简单使用。

第一步:服务端监听某个端口

第二步:客户端向服务端地址和端口发起socket连接请求

第三步:服务端收到连接请求后创建socket连接,并维护这个连接队列。

第四步:客户端和服务端已经建立双工通信(即双向通信),客户端和服务端可以轻松方便的给彼此发送信息。

至于简单使用的具体实现代码全部被我封装到项目中了,如果需要学习简单的实现,可以看我的源码,也可以自行百度,有很多的教程

2、核心,框架的使用

其实,说其为框架,可能有点牵强,因为每个人对框架都有自己的理解,但是类库和框架又有什么本质区别呢?全部都是代码~哈哈,扯远了

首先,空说无凭,先放上所有的代码:

服务端源文件:

socketserver.cs

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
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
 }
}

上面放上的是框架代码,接下来介绍下如何使用

首先,服务端使用方式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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;
   }
  }
 }
}

客户端使用方式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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);
    }
   }
  }
 }
}

最后运行测试截图:

C# .NET中Socket简单实用框架的使用教程

总结:

其最方便之处在于,将如何创建连接封装掉,使用人员只需关注连接后发送什么数据,接收到数据后应该如何处理,等等其它的很多事件的处理,这其中主要依托于匿名委托的使用,lambda表达式的使用。

框架里面主要使用了异步通讯,以及如何控制连接,详细我就不多说了,大家应该一看就懂,我只希望能给大家带来便利。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

最后,附上所有源码项目地址,若觉得有一定价值,还请点赞~

github地址:https://github.com/coldairarrow/sockets

原文链接:http://www.cnblogs.com/coldairarrow/p/7501645.html

延伸 · 阅读

精彩推荐
  • C#浅谈C# winForm 窗体闪烁的问题

    浅谈C# winForm 窗体闪烁的问题

    下面小编就为大家带来一篇浅谈C# winForm 窗体闪烁的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网7962021-12-21
  • C#c#学习之30分钟学会XAML

    c#学习之30分钟学会XAML

    一个界面程序的核心,无疑就是界面和后台代码,而xaml就是微软为构建应用程序界面而创建的一种描述性语言,也就是说,这东西是搞界面的...

    C#教程网8812021-12-10
  • C#C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    这篇文章主要介绍了C#实现的文件操作封装类,结合完整实例形式分析了C#封装文件的删除,移动,复制,重命名等操作相关实现技巧,需要的朋友可以参考下...

    Rising_Sun3892021-12-28
  • C#聊一聊C#接口问题 新手速来围观

    聊一聊C#接口问题 新手速来围观

    聊一聊C#接口问题,新手速来围观,一个通俗易懂的例子帮助大家更好的理解C#接口问题,感兴趣的小伙伴们可以参考一下...

    zenkey7072021-12-03
  • C#Unity3D UGUI实现缩放循环拖动卡牌展示效果

    Unity3D UGUI实现缩放循环拖动卡牌展示效果

    这篇文章主要为大家详细介绍了Unity3D UGUI实现缩放循环拖动展示卡牌效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    诗远3662022-03-11
  • C#C# 后台处理图片的几种方法

    C# 后台处理图片的几种方法

    本篇文章主要介绍了C# 后台处理图片的几种方法,非常具有实用价值,需要的朋友可以参考下。...

    IT小伙儿10162021-12-08
  • C#C#直线的最小二乘法线性回归运算实例

    C#直线的最小二乘法线性回归运算实例

    这篇文章主要介绍了C#直线的最小二乘法线性回归运算方法,实例分析了给定一组点,用最小二乘法进行线性回归运算的实现技巧,具有一定参考借鉴价值,需要...

    北风其凉8912021-10-18
  • C#C#基础之泛型

    C#基础之泛型

    泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。接下来通过本文给大家介绍c#基础之泛型,感兴趣的朋友一起学习吧...

    方小白7732021-12-03