我已经为我的客户创建了一个SslStream抽象类,如果需要的话,我希望您为我检查并增强它
SecureStream.cs
using System;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Program.Connections.Packets;
using Program.Core.Misc;
namespace Program.Connections.Network
{
public abstract class SecureStream
{
private static readonly byte[] Buffer = new byte[0x1f80];
private const string IpAddress = "192.168.1.65";
private readonly int _port;
private readonly Socket _socket;
private SslStream _sslStream;
public abstract void Receive(byte[] buffer);
public abstract void Error(Exception e);
protected SecureStream(int port)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
_port = port;
}
public void Connect()
{
_socket.BeginConnect(new IPEndPoint(IPAddress.Parse(IpAddress), _port), Authenticate, null);
}
private async void Authenticate(IAsyncResult ar)
{
try
{
var onCertificateValidationCallBack =
new RemoteCertificateValidationCallback(
OnCertificateValidation);
_sslStream = new SslStream(new NetworkStream(_socket, true), false, onCertificateValidationCallBack);
await _sslStream.AuthenticateAsClientAsync(IpAddress);
if (!_sslStream.IsAuthenticated) throw new Exception("not^authenticated");
do
{
var size = await _sslStream.ReadAsync(Buffer, 0, Buffer.Length);
if (size == 0) throw new Exception("invalid^size");
var buffer = new byte[size];
Native.MemoryCopy(Buffer, buffer, (uint)buffer.Length);
Receive(buffer);
Array.Clear(Buffer, 0, Buffer.Length);
} while (_sslStream.CanRead);
}
catch (Exception e)
{
Error(e);
}
}
internal async Task Send(PacketWriter writer)
{
var buffer = writer.GetWorkspace();
await _sslStream.WriteAsync(buffer, 0, buffer.Length);
}
private static bool OnCertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
{
return true;
}
}
}CoreServer.cs
using System;
using System.Windows.Forms;
namespace Program.Connections.Network
{
public sealed class CoreServer : SecureStream
{
public CoreServer(int p) : base(p) { }
public override void Receive(byte[] buffer)
{
//TODO: Handle The Buffer
}
public override void Error(Exception e)
{
//TODO: Add Error Writer.
MessageBox.Show(
string.Format("Disconnected from the server."),
string.Format("Connection Error"), MessageBoxButtons.OK,
MessageBoxIcon.Error);
Environment.Exit(1);
}
}
}我只需使用
var coreServer = new CoreServer(/*port*/);
coreServer.Connect();发布于 2012-10-27 19:53:51
new byte[0x1f80]我认为在这里使用十进制会更容易读懂。我不明白为什么你的缓冲区是8096字节,通常的大小是2的幂,比如8192。
IpAddress = "192.168.1.65"这看起来是一个完美的例子,它应该是可配置的,而不是一成不变的。您应该接受构造函数中的IP地址,就像您已经使用端口号一样。
public abstract void Receive(byte[] buffer);
public abstract void Error(Exception e);我不确定我喜欢在这里使用继承。我认为使用事件或类似的东西在这里会更有意义。
_socket.BeginConnect(…)我不喜欢您使用旧的异步编程模型,而您可以(在代码的其他部分)使用async-await。不幸的是,Socket不公开await可实现的方法,而是公开有很多方法可以避免。
private async void Authenticate(IAsyncResult ar)我认为Authenticate不是这个方法的好名字,它不仅仅是身份验证。
throw new Exception("not^authenticated")您不应该抛出Exception,您应该创建一个从Exception派生的自定义类并使用它。而异常信息应该是人类可读的,而不是像你所看到的那样的错误代码。如果您需要区分不同的错误,可以为它们具有不同的异常类型,或者为此向自定义异常添加属性。
if (size == 0) throw new Exception("invalid^size");当ReadAsync()返回0时,它的大小不是无效的,它意味着流的末尾已经到达,因此您应该采取相应的行动。
Native.MemoryCopy(Buffer, buffer, (uint)buffer.Length);为什么在这里使用自定义内存复制方法?你有什么理由不使用Buffer.BlockCopy()吗?还有,你为什么要在这里复制?您的类似乎只用于有限的用途(因为您有一个恒定的IP地址),所以您不能确保在Receive()返回后没有使用缓冲区,所以根本不必复制吗?
return true;我不是保安方面的专家,但我认为你至少应该对这里的证书进行一些检查。否则,您的类并不是真正的“安全流”。
MessageBox.Show(…);你不应该把这样的代码和GUI代码混在一起,它们应该分开。
https://codereview.stackexchange.com/questions/17978
复制相似问题