异步tcp客户端服务器。如何确定客户端或服务器不再可用?

时间:2015-04-12 14:44:45

标签: c# tcplistener

我想写异步tcp客户端服务器。当我在客户端上调用disconnect方法或在服务器上调用stop方法时,我写了这段代码但有问题。我没有得到异常,我无法确定客户端或服务器不再可用。如何确定客户端或服务器不再可用?

服务器

public class Server
{
    private readonly Dictionary<IPEndPoint, TcpClient> clients = new Dictionary<IPEndPoint, TcpClient>();

    private readonly List<CancellationTokenSource> cancellationTokens = new List<CancellationTokenSource>();

    private TcpListener tcpListener;

    private bool isStarted;

    public event Action<string> NewMessage;

    public async Task Start(int port)
    {
        this.tcpListener = TcpListener.Create(port);

        this.tcpListener.Start();

        this.isStarted = true;
        while (this.isStarted)
        {
            var tcpClient = await this.tcpListener.AcceptTcpClientAsync();

            var cts = new CancellationTokenSource();
            this.cancellationTokens.Add(cts);

            await Task.Factory.StartNew(() => this.Process(cts.Token, tcpClient), cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
    }

    public void Stop()
    {
        this.isStarted = false;

        foreach (var cancellationTokenSource in this.cancellationTokens)
        {
            cancellationTokenSource.Cancel();
        }

        foreach (var tcpClient in this.clients.Values)
        {
            tcpClient.GetStream().Close();
            tcpClient.Close();
        }

        this.clients.Clear();
    }

    public async Task SendMessage(string message, IPEndPoint endPoint)
    {
        try
        {
            var tcpClient = this.clients[endPoint];
            await this.Send(tcpClient.GetStream(), Encoding.ASCII.GetBytes(message));
        }
        catch (Exception exception)
        {
        }
    }

    private async Task Process(CancellationToken cancellationToken, TcpClient tcpClient)
    {
        try
        {
            var stream = tcpClient.GetStream();
            this.clients.Add((IPEndPoint)tcpClient.Client.RemoteEndPoint, tcpClient);

            while (!cancellationToken.IsCancellationRequested)
            {
                var data = await this.Receive(stream);
                this.NewMessage.SafeInvoke(Encoding.ASCII.GetString(data));
            }
        }
        catch (Exception exception)
        {
        }
    }

    private async Task Send(NetworkStream stream, byte[] buf)
    {
        await stream.WriteAsync(BitConverter.GetBytes(buf.Length), 0, 4);
        await stream.WriteAsync(buf, 0, buf.Length);
    }

    private async Task<byte[]> Receive(NetworkStream stream)
    {
        var lengthBytes = new byte[4];
        await stream.ReadAsync(lengthBytes, 0, 4);

        var length = BitConverter.ToInt32(lengthBytes, 0);
        var buf = new byte[length];

        await stream.ReadAsync(buf, 0, buf.Length);
        return buf;
    }
}

客户端

public class Client
{
    private TcpClient tcpClient;

    private NetworkStream stream;

    public event Action<string> NewMessage;

    public async void Connect(string host, int port)
    {
        try
        {

            this.tcpClient = new TcpClient();
            await this.tcpClient.ConnectAsync(host, port);
            this.stream = this.tcpClient.GetStream();

            this.Process();
        }
        catch (Exception exception)
        {

        }
    }

    public void Disconnect()
    {
        try
        {
            this.stream.Close();
            this.tcpClient.Close();
        }
        catch (Exception exception)
        {

        }
    }

    public async void SendMessage(string message)
    {
        try
        {
            await this.Send(Encoding.ASCII.GetBytes(message));
        }
        catch (Exception exception)
        {
        }
    }

    private async void Process()
    {
        try
        {
            while (true)
            {
                var data = await this.Receive();
                this.NewMessage.SafeInvoke(Encoding.ASCII.GetString(data));
            }
        }
        catch (Exception exception)
        {
        }
    }

    private async Task Send(byte[] buf)
    {
        await this.stream.WriteAsync(BitConverter.GetBytes(buf.Length), 0, 4);
        await this.stream.WriteAsync(buf, 0, buf.Length);
    }

    private async Task<byte[]> Receive()
    {
        var lengthBytes = new byte[4];
        await this.stream.ReadAsync(lengthBytes, 0, 4);

        var length = BitConverter.ToInt32(lengthBytes, 0);
        var buf = new byte[length];

        await this.stream.ReadAsync(buf, 0, buf.Length);
        return buf;
    }
}

0 个答案:

没有答案