Reputation: 549
I'm new to C# and sockets so I apologize if my questions are out of line. I started building a socket interface using the example in this link: https://code.msdn.microsoft.com/High-Performance-NET-69c2df2f
I want to be able to transfer binary files across the socket so I made an assumption (maybe the wrong one) that I should not use StringBuilder
. I changed the OSUserToken
from the original to use a MemoryStream
and BinaryWriter
(commenting out the original code).
Elsewhere in the code (from the link above), SocketAsyncEventArgs
is intialized with SetBuffer(new Byte[_bufferSize], 0, _bufferSize);
. I'm concerned this will not mesh well with my MemoryStream
and BinaryWriter
but it seems to work.
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();
}
}
}
When I run this, it seems to work without an issue. Even if I set the protected const int DEFAULT_BUFFER_SIZE = 1
it will accept a stream of >1 bytes:
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.
My questions are these:
StringBuilder
wouldn't work for binary files and I should use MemoryStream
and BinaryWriter
?SocketAsyncEventArgs
is initialized with SetBuffer(new Byte[_bufferSize], 0, _bufferSize);
?Upvotes: 0
Views: 436
Reputation: 549
I found answers to my questions
StringBuilder
works fine. Just encode the strings in base64
before sending and decode after receiving. This should be done no matter if sending text or binary data. See the class I wrote below.StringBuilder
& base64
works with binary, this question is no longer relevant.0xFFFFF
.Class for encoding/decoding 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;
}
}
Upvotes: 0