2017-06-19 36 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; 
    } 
}