2012-07-28 41 views
2

我有问题,我试图以base64格式发送数据。来自客户端的发送很好。但如果即时通讯尝试在服务器上反编译base64,即时通讯仍然总是出现错误,无效的base64文字记录器。C#异步套接字:发送数据base64编码?

我在寻找一种方法来加密客户端到服务器的数据并在服务器上解密它,以实现安全传输。

我的代码显示了ATM这样的: 客户:

socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
socket.BeginConnect(ipAddress, ipAddressPort, new AsyncCallback(testA), null); 

protected static void testA (IAsyncResult ar) { 
     socket.EndConnect(ar); 
     string str = EncodeTo64("Hello world!"); 
     socket.BeginSend(System.Text.Encoding.UTF8.GetBytes(str), 0, str.Length, SocketFlags.None, new AsyncCallback(testB), socket); 
    } 
    protected static void testB (IAsyncResult ar) { 
     socket.EndSend(ar); 
     socket.BeginReceive(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(testC), socket); 
    } 
    protected static void testC (IAsyncResult ar) { 
     socket.EndReceive(ar); 
     MessageBox.Show(System.Text.Encoding.UTF8.GetString(bytes)); 
    } 
    static public string EncodeTo64(string toEncode) 
    { 
     byte[] toEncodeAsBytes 
      = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode); 
     string returnValue 
      = System.Convert.ToBase64String(toEncodeAsBytes); 
     return returnValue; 
    } 
    static public string DecodeFrom64(string encodedData) 
    { 
     byte[] encodedDataAsBytes 
      = System.Convert.FromBase64String(encodedData); 
     string returnValue = 
     System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes); 
     return returnValue; 
    } 

服务器:

serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 4444); 

serverSocket.Bind(ipEndPoint); 
serverSocket.Listen(4); 


serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); 

protected static byte[] byteData = new byte[1024]; 
private void OnAccept(IAsyncResult ar) 
    { 
     Socket clientSocket = serverSocket.EndAccept(ar); 

     //Start listening for more clients 
     serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); 

     //Once the client connects then start receiving the commands from her 
     // Create the state object. 
     clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, 
      new AsyncCallback(OnReceive), clientSocket); 
    } 

private void OnReceive(IAsyncResult ar) { 
     Socket clientSocket = (Socket)ar.AsyncState; 
     clientSocket.EndReceive(ar); 
MessageBox.Show(DecodeFrom64(System.Text.Encoding.UTF8.GetString(byteData))); 
} 
    static public string EncodeTo64(string toEncode) 
    { 
     byte[] toEncodeAsBytes 
      = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode); 
     string returnValue 
      = System.Convert.ToBase64String(toEncodeAsBytes); 
     return returnValue; 
    } 
    static public string DecodeFrom64(string encodedData) 
    { 
     byte[] encodedDataAsBytes 
      = System.Convert.FromBase64String(encodedData); 
     string returnValue = 
     System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes); 
     return returnValue; 
    } 
    public void OnSend(IAsyncResult ar) { 
     Socket client = (Socket)ar.AsyncState; 
     client.EndSend(ar); 
    } 
+0

只是想知道...为什么你要发送一个字符串作为字符串=> Ascii => base64 => UTF8?这是否与特别期望base-64的API交谈?如果没有,你应该**只使用UTF8(其余不需要)。这是否正在运行时,是否打算将“ASCII”替换为“加密”?如果是这样的话:那么没有理由使用base-64/UTF8步骤:只发送二进制文件 – 2012-07-28 07:21:01

+0

您收到的字节是否与您发送的字节匹配?特别要注意的是这是**不能保证**;您不会一直接收您发送的相同数据块中的数据。您应该考虑一个“成帧”协议 - 最简单的方法是,在每封邮件中装入以下邮件中的字节数,以便接收方知道何时收到完整的邮件。 – 2012-07-28 07:24:30

+0

@MarcGravell他正在使用TCP和TCP保证可靠的字节流。这意味着他确实按照发送数据的顺序接收数据。 – 2012-07-28 08:32:10

回答

1

正如马克Gravell写的,你不必要的网络协议复杂化。网络传输本质上是复杂的,所以避免任何不必要的复杂性!

当他说你必须确保你真的阅读了所有发送的数据时,他也是绝对正确的。请看看那里的文档和示例(特别是Socket classSocket.EndReceive;请注意,只是调用EndReceive不足以确保读取所有内容)。主要的一点是:您需要在服务器端进行循环,以确保所有发送数据都已被读取。如果要发送的数据简单并且网络非常可靠(请参阅:本地以太网通过电缆,没有WiFi;互联网,特别是移动互联网不可靠),也许只是一个循环,直到没有更多的数据到达可能是足够的;在任何更复杂的情况下,使用Marc建议的成帧协议会更明智,这将提供更可靠的方式来决定何时结束读取循环。

您可以用下面的代码容易地再现您的错误:

var data = Encoding.ASCII.GetBytes("Hello World!"); 
var base64 = Convert.ToBase64String(data); 
var bytesToSend = Encoding.UTF8.GetBytes(base64); 
var stringRecieved = Encoding.UTF8.GetString(bytesToSend).Substring(0, 5); 
var decoded = Convert.FromBase64String(stringRecieved); 
var result = Encoding.ASCII.GetString(decoded); 
Console.WriteLine("{0} -> {1} -> {2}", base64, stringRecieved, result); 

.Substring(0, 5)模拟尚未完全读取网络流。如果你删除.Substring然后一切工作正常。要支持Marcs点,以下就足以发送数据了:

var bytesToSend = Encoding.UTF8.GetBytes("Hello World!"); 
var stringRecieved = Encoding.UTF8.GetString(bytesToSend); 

另一个重要说明:BASE64与加密完全无关。它只是一种编码,如UTF8或ASCII。如果您需要安全的通信通道,BASE64不是解决方案!如果窃听者读取BASE64编码的消息,他可以轻松识别编码,然后轻松解码。

如果您需要安全通道,请使用强加密标准(如AES)或使用TLS等安全网络协议(例如,通过HTTPS;使用HTTPS也可以解决由Marc Gravell提到的针对更复杂数据的“框架”问题交流)。

+0

非常感谢! :-)它很适合MSDN的例子。 ;-)收到数据的循环是问题.. – user1558672 2012-07-28 09:51:57