2017-06-19 70 views
-1

我是新来C#和套接字,所以我很抱歉,如果我的问题是不符合要求的。我开始建设使用这个链接的例子一个套接字接口: https://code.msdn.microsoft.com/High-Performance-NET-69c2df2fSocketAsyncEventArgs与二进制/字节[]流

我希望能够让我做一个假设(也许是错误的),我不应该使用StringBuilder传输通过套接字二进制文件。我将原来的OSUserToken更改为使用MemoryStreamBinaryWriter(注释掉原始代码)。

在代码的其他地方(来自上面的链接),SocketAsyncEventArgs使用SetBuffer(new Byte[_bufferSize], 0, _bufferSize);进行初始化。我担心这不会与我的MemoryStreamBinaryWriter吻合,但它似乎有效。

sealed class UserToken : IDisposable 
{ 
    private Socket _ownerSocket; 
    public Socket ownerSocket { get { return _ownerSocket; } } 

    private MemoryStream _memoryStream; 
    private BinaryWriter _binaryWriter; 
    //private StringBuilder stringbuilder; 

    private int totalByteCount; 

    public String LastError; 

    public UserToken(Socket readSocket, int bufferSize) 
    { 
     _ownerSocket = readSocket; 
     _memoryStream = new MemoryStream(); 
     _binaryWriter = new BinaryWriter(_memoryStream); 
     //stringbuilder = new StringBuilder(bufferSize); 
    } 

    // Do something with the received data, then reset the token for use by another connection. 
    // This is called when all of the data have been received for a read socket. 
    public void ProcessData(SocketAsyncEventArgs args) 
    { 
     String received = System.Text.Encoding.ASCII.GetString(_memoryStream.ToArray()); 
     //String received = stringbuilder.ToString(); 

     Debug.Write("Received: \"" + received + "\". The server has read " + received.Length + " bytes."); 

     _memoryStream.SetLength(0); 
     //stringbuilder.Length = 0; 
     totalByteCount = 0; 
    } 

    public bool ReadSocketData(SocketAsyncEventArgs readSocket) 
    { 
     int byteCount = readSocket.BytesTransferred; 

     /* 
     if ((totalByteCount + byteCount) > stringbuilder.Capacity) 
     { 
      LastError = "Receive Buffer cannot hold the entire message for this connection."; 
      return false; 
     } 
     else 
     { 
     */ 
      //stringbuilder.Append(Encoding.ASCII.GetString(readSocket.Buffer, readSocket.Offset, byteCount)); 
      _binaryWriter.Write(readSocket.Buffer,readSocket.Offset,byteCount); 
      totalByteCount += byteCount; 
      return true; 
     /*}*/ 
    } 

    public void Dispose() 
    { 
     _memoryStream.Dispose(); 
     _binaryWriter.Dispose(); 
     try 
     { 
      _ownerSocket.Shutdown(SocketShutdown.Both); 
     } 
     catch 
     { 
      //Nothing to do here, connection is closed already 
     } 
     finally 
     { 
      _ownerSocket.Close(); 
     } 
    } 
} 

当我运行这个,它似乎工作没有问题。即使我设置protected const int DEFAULT_BUFFER_SIZE = 1将接受> 1个字节流:

17:11:20:433 - Debug - Initializing the listener on port 5000... 
17:11:20:439 - Debug - Starting the listener... 
17:11:20:444 - Debug - Server started. 
17:11:31:856 - Debug - Received: "listener". The server has read 8 bytes. 
17:11:33:264 - Debug - Received: "l". The server has read 1 bytes. 
17:11:33:268 - Debug - Received: "istener". The server has read 7 bytes. 
17:11:36:744 - Debug - Received: "l". The server has read 1 bytes. 
17:11:36:744 - Debug - Received: "i". The server has read 1 bytes. 
17:11:36:746 - Debug - Received: "stener". The server has read 6 bytes. 

我的问题是:

  1. 我是正确的,StringBuilder不会为二进制文件工作,我应该使用MemoryStreamBinaryWriter
  2. 如果程序中的其他地方,SocketAsyncEventArgs初始化为SetBuffer(new Byte[_bufferSize], 0, _bufferSize);,我需要关心缓冲区溢出吗?
  3. 如果我必须服从缓冲区大小限制,是否需要在我的客户端发送数据时使用相同的缓冲区限制?

回答

0

我找到答案,我的问题

  1. StringBuilder工作正常。只需在接收之前在发送和解码之前对base64中的字符串进行编码。无论发送文本还是二进制数据,都应该这样做。看到我在下面写的课。
  2. 还不知道这个问题的答案,但看到的是StringBuilder & base64与二进制工作,这个问题已不再相关。
  3. 我认为这个问题的答案是肯定的。客户端应该有一个最大消息长度。我基于套接字的标题部分来控制消息的长度。标题长度固定,我的最大消息长度为0xFFFFF

用于编码/解码的base64类别:

public static class Base64 
{ 
    public static string EncodeBase64(string text) 
    { 
     return System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(text)); 
    } 

    public static string EncodeBase64(byte[] array) 
    { 
     return System.Convert.ToBase64String(array); 
    } 

    public static string DecodeBase64ToString(string base64String) 
    { 
     return System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(base64String)); 
    } 

    public static Byte[] DecodeBase64ToBinary(string base64String) 
    { 
     Byte[] bytes = System.Convert.FromBase64String(base64String); 
     return bytes; 
    } 
}