简单的网络编程





5.00/5 (4投票s)
一种简单的网络编程方法
引言
大约 5 年前,当我开始编程时,我曾怀揣着远大的梦想。我想从零开始构建一个完美无瑕的聊天系统,它必须快速、可靠且轻量级。
然而,对于新手程序员来说,大多数雄心勃勃的项目都会很快夭折,这个项目也不例外。我搜索并努力寻找一个合适的系统或代码,以便能够与一个中心化服务器上的两个客户端进行简单的通信。显然,这对我来说非常困难(直到几年后我才精通 Google 搜索),我找不到任何能完全满足我需求的东西。
几年过去了,我积累了更多技能,于是我决定,“嘿,我应该写那个聊天系统”。于是我照做了。结果很糟糕,但我学到了很多东西。RattleSnake
就是我学到的东西的一个例子。
背景
我想要一个灵活的系统,能够接受我给它的任何东西,并产生我想要的结果。这听起来可能很愚蠢,但请听我说。我希望能够序列化结构,或者在不改变发送方式的情况下发送自定义编码的字节数组。RattleSnake
就能做到这一点。
这个项目最初只是一个个人项目,但后来发展成了庞大的工程。RattleSnake
几乎可以处理你想要的任何事情,从客户端-服务器连接,到处理 UPnP。
RattleSnake
包含 4 个主要命名空间
RattleSnake.Client
RattleSnake.Client.Client
RattleSnake.Client.TcpClientEx
RattleSnake.Server
RattleSnake.Server.Server
RattleSnake.Server.TcpListenerEx
RattleSnake.Security
RattleSnake.Security.WhirlpoolManaged
- 请注意,这个类并非我创作。我只是将其从 C# 转换而来。原始许可证和注释仍然保留,以归功于原作者。
RattleSnake.Security.MersenneTwister
- 与
WhirlpoolManaged
一样,我没有创建这个类。我只是将其从 C# 转换而来。原始许可证和注释仍然保留,以归功于原作者。
- 与
RattleSnake.Security.Encryption
RattleSnake.UPnP
每个命名空间的内容和功能都非常清晰。
我不得不进行一些继承,例如继承 TcpClient
和 TcpListener
以便提供未来的功能(例如 MyBase.Active()
属性),并在我更新这个项目时使用。不过,目前 RattleSnake
相对完整,只差一些我想添加的新功能。
Using the Code
使用 RattleSnake
的客户端、服务器、UPnP
和安全功能极其简单。客户端和服务器完全是事件驱动的,这使得理解它们非常容易。
下面是一个使用客户端的简单示例
' This is for the Client.
Dim _rsc As New RattleSnake.Client.RattleSnakeClient()
' Now perform a connection
_rsc.Connect("127.0.0.1", 6110)
要执行连接,只需要以上代码。但是,我们如何跟踪客户端何时连接?接收数据、断开连接或异常又如何处理呢?RattleSnakeClient
类提供了事件来处理所有这些情况。
Public Event ConnectionEstablished(ByVal sender As Object, _
ByVal e As EventArgs.RattleSnakeClientConnectionEstablishedEventArgs)
当建立连接时,将触发此事件。传递的 EventArgs
包含以下属性:
IP
- 返回客户端连接的 IP 地址(作为String
)。Port
- 返回客户端连接的端口号(作为Port
)。
Public Event DataReceived(ByVal sender As Object, _
ByVal e As EventArgs.RattleSnakeClientDataReceivedEventArgs)
当通过连接传输 Data
时,将触发此事件。传递的 EventArgs
包含以下属性:
Data
- 返回一个字节数组,其中包含接收到的所有数据。Object
- 尝试通过序列化返回一个表示接收到的Data
的对象。如果序列化失败,则返回一个New Object
。
Public Event Exception(ByVal sender As Object, _
ByVal e As EventArgs.RattleSnakeClientExceptionEventArgs)
当 RattleSnakeClient
抛出异常时,将触发此事件。传递的 EventArgs
包含以下属性:
Exception
- 返回抛出的异常。
这些事件简单明了,并确保 RattleSnake
顺利运行。
使用 RattleSnake
发送数据同样极其简单。
'Define some random data in a Byte Array; filled with junk data or what not.
Dim _data As new Byte(255)
'Now send it with RattleSnake
_rsc.BeginSend(_data)
使用 RattleSnake
发送数据就是这么简单。你也可以简单地将一个可序列化的 Object
传递给 .BeginSend()
方法,它也会被发送;RattleSnake
在内部使用了这个功能。
断开连接同样轻而易举。
'Disconnect.
_rsc.Disconnect(True)
在 RattleSnake
中,除非确实重要,否则 .Disconnect()
总是会取一个 True
值。这个 True
值会告诉 RattleSnake
通知对方正在发生断开连接。我这样做只是为了确保对方不会收到本可以避免的异常。
现在,简单介绍一下 RattleSnake
中的 UPnP
类。UPnP
类允许快速方便地在支持 UPnP
的设备上添加(或删除)端口映射。以下是 UPnP
类的方法、属性和枚举列表:
- 协议
- TCP
- UDP
Add()
Remove()
Exists()
LocalIP()
Print()
Dispose()
每个方法都有 XML 风格的注释,所以我在这里不详细介绍,但在支持 UPnP
的设备上添加端口映射非常容易。
Using rs = New RattleSnake.UPnP.UPnP
rs.Add(RattleSnake.UPnP.UPnP.LocalIP(), 100,
RattleSnake.UPnP.UPnP.Protocol.TCP, "Description")
End Using
仅此而已就可以为支持 UPnP
的设备添加端口映射。该代码将映射添加到本地 IP 地址,端口号为 100,协议为 TCP,描述为 "Description
"。删除操作同样简单。
Using rs = New RattleSnake.UPnP.UPnP
rs.Remove(100, RattleSnake.UPnP.UPnP.Protocol.TCP)
End Using
刚才添加的端口现在已被删除。Add()
和 Remove()
例程在内部调用 Exists()
,因此程序员不需要自己执行此操作(但是,该类会抛出 ArgumentException()
)。
总的来说,RattleSnake
不应该存在太多 bug。它已经经过了多次实际测试,几乎没有出现什么错误,但如果出现任何 bug,我会尽力尽快修复。
关注点
我应该指出,RattleSnake
已经经历了几次重写。截至 2011 年 12 月 5 日,这是 RattleSnake
的第三次重写,目的是提供更清晰、更高效的代码。UPnP
是 RattleSnake
的一个近期添加功能,我为此花费了一些研究时间,以弄清楚如何在 Windows 中轻松实现它。我在这里使用的“轻松”这个词比较随意,因为相对简单,但需要一些琢磨才能使其正常工作(例如,它似乎只在 .NET 3.5 及以上版本中有效,因为 .NET 2.0 中没有暴露所需的接口)。
历史
- 2011 年 12 月 5 日 - 初始发布