Library, that provides Mailbox class. The Mailbox class is a shell for a Socket object for a more simple network packets sending and receiving. So it segments TCP traffic for packets and returns data in this view.
- Get the Socket object
- Create Mailbox by
Mailbox mailbox = new Mailbox(socket)
Network packets sending and receiving completes by mailbox.tick();
function in the NonBlocking mode. I.E. the best solution is to call this method with some interval (you can create a special thread to call this). mailbox.tick();
returns false when an error occurs or remote host is diconnected
- Create Packet object by
Packet packet = new Packet([yourdata : byte[]]);
(for examplePacket packet = new Packet(Encoding.UTF8.GetBytes("Hello!"))
) - To send packet call
mailbox.Send(packet)
- Call
mailbox.Tick()
- Call
mailbox.Tick()
in main or other thread with some time intervals - To receive packet on connected host use
mailbox.Next()
to get a packet if any packet is received (null else) ormailbox.GetAllReceived()
to get all received packets at the call time
!!! Don't forget to callmailbox.Tick()
!!! - Received data bytes array is in packet.data field
Mailbox class has constructor: public Mailbox(Socket socket, int maxReceiveFragmentsPerTick = 64, int sendPacketsPerTick = 0, int maxPacketSize = 0)
Socket socket
- socket that this object will be the facade ofint maxReceiveFragmentsPerTick
- limit of received fragments per tickint sendPacketsPerTick
- limit of packets, that can be sended per tickint maxPacketSize
- limit of received packet size
!!! Do not use asynchronous packets listening with ticks !!!
Task StartListenAsync(int receivePacketsPerSecond = 0, CancellationToken cancellationToken = default)
- start to receive and send packets asynchronouslyvoid StopListen(bool interruptSendingWhenAll = false)
- stop receive and send packets asynchronously. IfinterruptSendingWhenAll
is True, the packets sender will send all the packets in the send queue before stoppingTask StopListenAsync(bool interruptSendingWhenAll = false)
- the same as theStopListen
method, but returns a Task, that will be finished when the send and the receive tasks will be finishedvoid StopListenWait(bool interruptSendingWhenAll = false)
- the same as theStopListen
method, but blocks the call thread until the send and the receive tasks will be finishedTask<Packet> GetNextAsync(CancellationToken cancellationToken = default)
- get the next packet or waitTask<IEnumerable<Packet>> GetAllReceivedAsync(CancellationToken cancellationToken = default)
get all received packets if exist or waits for new packet otherwice
bool IsConnected
- checks if socket is connected (Connected socket property)int SendQueueSize
- get the number of currently processed packetsint ReceivedCount
- get the number of received packets in the queueint SendQueueSize
- get send queue sizevoid Close()
- close socketbool IsSendQueueEmpty
- checks if send queue is emptyvoid ClearReceived()
- clears received packet queuevoid ClearReceivedQueue()
- clears send packet queuevoid ClearAll()
- clears both packet queuesPacket Packet.CloneDataRef()
- returns new ready for sending Packet with some data ref
- You can set owner object of mailbox by
void SetOwner(IMailboxOwner)
method and get it byTYPE GetOwner<TYPE>()
method. - Owner object must implement IMailboxOwner interface and have MailboxSafe object
For example:
public class ClientInfo : IMailboxOwner {
public MailboxSafe MailboxSafe { get; } = new MailboxSafe();
}
- Also call
mailbox.RemoveOwner()
to remove owner object link. - Owner link methods are thread-safe, but don't use it too often. The purpose of these methods is to bind mailbox owner object in the start of handling
- Also you can use
GetMailbox
,SetMailbox
,RemoveMailbox
IMailboxOwner's extension methods. They call similar methods in owned mailbox
(You can find the Test project in this repository MailboxShell solution) Lightweight example:
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(IPAddress.Parse(SERVER_IP), SERVER_PORT);
Mailbox mailbox = new Mailbox(socket);
while(true) {
string message = Console.ReadLine();
mailbox.Send(new Packet(Encoding.UTF8.GetBytes(message)));
while(true) {
mailbox.Tick();
Packet receivedPacket = mailbox.Next(); //Try to get the next packet
if(receivedPacket != null) {
Console.WriteLine($"Server response: \"{Encoding.UTF8.GetString(receivedPacket.data)}\"");
break;
}
Thread.sleep(1);
}
}
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
serverSocket.Listen(10);
Mailbox mailbox = new Mailbox(serverSocket.Accept());
while(true) {
mailbox.Tick(); //Tick to receive
foreach(Packet packet in mailbox.GetAllReceived()) {
string message = Encoding.UTF8.GetString(packet.data); //Get message from packet.data
mailbox.Send(new Packet(Encoding.UTF8.GetBytes("Echo: " + message))); //Send response
}
mailbox.Tick(); //Tick to send (but both ticks can be in one in this case)
Thread.sleep(1);
}
private async Task handlePackets(Mailbox mailbox, CancellationToken cancellationToken) {
while(!cancellationToken.IsCancellationRequested) {
Packet packet = await mailbox.GetNextAsync(cancellationToken);
string responseString = Encoding.UTF8.GetString(packet.data);
Console.WriteLine($"Server response: \"{responseString}\"");
}
}
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(IPAddress.Parse(SERVER_IP), SERVER_PORT);
Mailbox mailbox = new Mailbox(socket);
CancellationTokenSource cts = new CancellationTokenSource();
Task listenTask = mailbox.StartListenAsync(cts.Token);
Task handlePacketsTask = mailbox.handlePackets(cts.Token);
Console.ReadKey();
cts.Cancel();
Task.WaitAll(listenTask, handlePacketsTask);