• C# TcpListener的编程要点


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace Server
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                listener = new TcpListener(IPAddress.Any, 9009);// 端口根据需要确定
                listener.Start();
    
                // 后台线程1:用于接收tcp连接请求,并将网络流加入列表。随主线程的退出而退出。
                new Thread(() =>
                {
                    while (true)
                    {
                        Thread.Sleep(100);// 可以根据需要设置时间
                        if (!listener.Pending())
                        {
                            continue;
                        }
                        var client = listener.AcceptTcpClient();
                        // 下面属性根据需要进行设置
                        // client.ReceiveBufferSize
                        // client.ReceiveTimeout
                        // client.SendBufferSize
                        // client.SendTimeout
                        if (!client.Connected)
                        {
                            continue;
                        }
                        streams.Add(client.GetStream());
                    }
                }) { IsBackground = true }.Start();
    
                // 后台线程2:用于接收请求,并作出响应。随主线程的退出而退出。
                new Thread(() =>
                    {
                        while (true)
                        {
                            Thread.Sleep(100);// 可以根据需要设置时间
                            if (streams == null || streams.Count == 0)
                            {
                                continue;
                            }
                            streams = streams.Where(s => s.CanRead && s.CanWrite).ToList();
                            foreach (var stream in streams.Where(stream => stream.CanRead && stream.CanWrite))
                            {
                                AsyncReceiveBytes(stream,
                                    s =>
                                    {
                                        // todo:对result进行解码
                                        // todo:对收到指令进行逻辑判断,得出待响应的C#对象
                                        AsyncSendBytes(s, new byte[0]); // todo:将待响应的C#对象转换成字节数组,替换new byte[0]。
                                    });
                            }
                        }
                    }) { IsBackground = true }.Start();
            }
    
            // 发送事件和目标的入口
            public void SendEventAndTarget()
            {
                if (streams == null || streams.Count == 0)
                {
                    return;
                }
                streams = streams.Where(s => s.CanRead && s.CanWrite).ToList();
                foreach (var stream in streams.TakeWhile(stream => stream.CanWrite))
                {
                    AsyncSendBytes(stream, new byte[0]);// todo:这里将待发送的C#对象转换的字节数组替换new byte[0]。
                }
            }
    
            private static void AsyncReceiveBytes(NetworkStream stream,
                Action<NetworkStream> callback)
            {
                // 短时后台线程:用于处理网络流的读操作,处理完成后即归还线程池。
                // 每个网络流都会分配一个线程。
                //ThreadPool.SetMaxThreads();根据需要设置。
                ThreadPool.QueueUserWorkItem(delegate
                {
                    var buffer = new byte[1024];// 1024:根据需要进行设置。
                    var result = new byte[0];
                    do
                    {
                        var a = stream.Read(buffer, 0, buffer.Length);
                        result = result.Concat(buffer.Take(a)).ToArray();
                    } while (stream.DataAvailable);
                    callback(stream);
                });
            }
            private static void AsyncSendBytes(NetworkStream stream, byte[] bytes)
            {
                // 短时后台线程:用于处理网络流的写操作,处理完成后即归还线程池。
                // 每个网络流都会分配一个线程。
                //ThreadPool.SetMaxThreads();根据需要设置。
                ThreadPool.QueueUserWorkItem(delegate
                    {
                        try
                        {
                            stream.Write(bytes, 0, bytes.Count());
                        }
                        catch (Exception)
                        {
                            MessageBox.Show("远程主机主动断开此连接!");// 也可以做其它处理。
                        }
                    });
            }
    
            private readonly TcpListener listener;
            // 网络流列表
            private List<NetworkStream> streams = new List<NetworkStream>();
        }
    }

    找时间在项目中应用后,再总结一下。

  • 相关阅读:
    每日随笔
    每日随笔
    每日随笔
    JavaSE 类加载机制
    MySQL 索引
    JavaSE 线程的生命周期
    JVM堆内存(heap)详解
    Redis 学习笔记(三)哨兵模式配置高可用和集群
    sqlserver数据库连接数相关问题
    多项式多点求值
  • 原文地址:https://www.cnblogs.com/yao2yao4/p/3139341.html
Copyright © 2020-2023  润新知