123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- using System;
- using System.Threading.Tasks;
- using Vinno.IUS.Common.IO;
- using Vinno.IUS.Common.Network.Tcp;
- using Vinno.IUS.Common.Network.Tcp.Extensions;
- using Vinno.IUS.Common.Network.IO;
- namespace Vinno.IUS.Common.Network.Channels
- {
- public class ClientChannel:Channel
- {
- private readonly ITcp _tcp;
- private int _readTimeoutTranscationLevel;
- private int _writeTimeoutTranscationLevel;
- /// <summary>
- /// Gets the total data transfered include send and receive.
- /// </summary>
- public long DataTransfered { get; private set; }
- public ClientChannel(int channelId, ITcp tcp):base(channelId)
- {
- _tcp = tcp;
- Remote = _tcp.Remote;
- Local = _tcp.Local;
- }
- /// <summary>
- /// Read and validate the header from remote.
- /// </summary>
- /// <param name="timeout">Wait forever if the value is 0</param>
- protected override void ReadHeader(int timeout = 0)
- {
- //Notice that when network is shutdown, it may not know it's shutdown,
- //But when read data from socket, it will read 0 byte, that's can used for
- //Check if network is shutdown.
- using (new ReadTimeoutTranscation(this, timeout))
- {
- //ReadBinary may throw exception when network is shutdown, and readed data length is zero.
- var headerData = _tcp.ReadBinary(8);
- ValidateHeader(headerData);
- DataTransfered += 8;
- }
- }
- /// <summary>
- /// Read and validate the header from remote by async way.
- /// </summary>
- /// <param name="timeout">Wait forever if the value is 0</param>
- protected override async Task ReadHeaderAsync(int timeout = 0)
- {
- //Notice that when network is shutdown, it may not know it's shutdown,
- //But when read data from socket, it will read 0 byte, that's can used for
- //Check if network is shutdown.
- using (new ReadTimeoutTranscation(this, timeout))
- {
- //ReadBinary may throw exception when network is shutdown, and read data length is zero.
- var headerData = await _tcp.ReadBinaryAsync(8).ConfigureAwait(false);
- ValidateHeader(headerData);
- DataTransfered += 8;
- }
- }
- /// <summary>
- /// Write the header before write buffer.
- /// </summary>
- /// <param name="timeout">Wait forever if the value is 0</param>
- protected override void WriteHeader(int timeout = 0)
- {
- using (new WriteTimeoutTranscation(this, timeout))
- {
- var headerData = GetHeaderData();
- //Write header
- _tcp.WriteBinary(headerData);
- DataTransfered += 8;
- }
- }
- /// <summary>
- /// Write the header before write buffer by async way.
- /// </summary>
- /// <param name="timeout">Wait forever if the value is 0</param>
- protected override async Task WriteHeaderAsync(int timeout = 0)
- {
- using (new WriteTimeoutTranscation(this, timeout))
- {
- var headerData = GetHeaderData();
- //Write header
- await _tcp.WriteBinaryAsync(headerData).ConfigureAwait(false);
- DataTransfered += 8;
- }
- }
- /// <summary>
- /// Read buffer from remote side.
- /// </summary>
- /// <param name="timeout">Wait forever if the value is 0</param>
- /// <returns>The buffer readed from network.</returns>
- protected IBuffer ReadBuffer(int timeout = 0)
- {
- using (new ReadTimeoutTranscation(this, timeout))
- {
- var reader = new BufferReader(_tcp.ReadStream);
- var buffer = reader.ReadBuffer();
- DataTransfered += buffer.Size;
- return buffer;
- }
- }
- /// <summary>
- /// Read buffer from remote side by async way.
- /// </summary>
- /// <param name="timeout">Wait forever if the value is 0</param>
- /// <returns>The buffer readed from network.</returns>
- protected async Task<IBuffer> ReadBufferAsync(int timeout = 0)
- {
- using (new ReadTimeoutTranscation(this, timeout))
- {
- var reader = new AsyncBufferReader(_tcp.ReadStream);
- var buffer = await reader.ReadBufferAsync().ConfigureAwait(false);
- DataTransfered += buffer.Size;
- return buffer;
- }
- }
- /// <summary>
- /// Write buffer to remote side.
- /// </summary>
- /// <param name="buffer">The buffer to be writen</param>
- /// <param name="timeout">Wait forever if the value is 0</param>
- protected void WriteBuffer(IBuffer buffer, int timeout = 0)
- {
- using (new WriteTimeoutTranscation(this, timeout))
- {
- var writer = new BufferWriter(_tcp.WriteStream);
- writer.WriteBuffer(buffer);
- DataTransfered += buffer.Size;
- }
- }
- /// <summary>
- /// Write buffer to remote side by async way.
- /// </summary>
- /// <param name="buffer">The buffer to be writen</param>
- /// <param name="timeout">Wait forever if the value is 0</param>
- protected async Task WriteBufferAsync(IBuffer buffer, int timeout = 0)
- {
- using (new WriteTimeoutTranscation(this, timeout))
- {
- var writer = new AsyncBufferWriter(_tcp.WriteStream);
- await writer.WriteBufferAsync(buffer).ConfigureAwait(false);
- DataTransfered += buffer.Size;
- }
- }
- protected override void OnClosed()
- {
- _tcp.Disconnect();
- base.OnClosed();
- }
- public override string ToString()
- {
- return $"{Remote}<->{Local}";
- }
- private class ReadTimeoutTranscation : IDisposable
- {
- private readonly ClientChannel _channel;
- public ReadTimeoutTranscation(ClientChannel channel, int timeout)
- {
- _channel = channel;
- if (_channel._readTimeoutTranscationLevel == 0)
- {
- try
- {
- _channel._tcp.ReadTimeout = timeout;
- }
- catch
- {
- //DO Nothing.
- }
- }
- _channel._readTimeoutTranscationLevel++;
- }
- public void Dispose()
- {
- _channel._readTimeoutTranscationLevel--;
- if (_channel._readTimeoutTranscationLevel == 0)
- {
- try
- {
- _channel._tcp.ReadTimeout = 0;
- }
- catch
- {
- //DO Nothing.
- }
- }
- }
- }
- private class WriteTimeoutTranscation : IDisposable
- {
- private readonly ClientChannel _channel;
- public WriteTimeoutTranscation(ClientChannel channel, int timeout)
- {
- _channel = channel;
- if (_channel._writeTimeoutTranscationLevel == 0)
- {
- try
- {
- _channel._tcp.SendTimeout = timeout;
- }
- catch
- {
- //DO Nothing.
- }
- }
- _channel._writeTimeoutTranscationLevel++;
- }
- public void Dispose()
- {
- _channel._writeTimeoutTranscationLevel--;
- if (_channel._writeTimeoutTranscationLevel == 0)
- {
- try
- {
- _channel._tcp.SendTimeout = 0;
- }
- catch
- {
- //DO Nothing.
- }
- }
- }
- }
- }
- }
|