使用 NetworkStream.WriteAsync 检测错误

2024-06-25

如果我在调用后杀死我的服务器Login完成后,调用时不会引发异常stream.WriteAsync(data, 0, data.Count());已完成,并且返回的任务中没有错误指示。

那么,我应该如何检测错误呢?当然,应该有一些迹象表明我试图通过已挂断的连接发送数据。

这是我最新的代码尝试:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

using log4net;
using System.IO;
using System.Threading;

namespace IntegrationTests
{
    public class Client
    {
        private static readonly ILog log = LogManager.GetLogger("root");

        static private ulong m_lastId = 1;

        private ulong m_id;
        private string m_host;
        private uint m_port;
        private uint m_timeoutMilliseconds;
        private string m_clientId;
        private TcpClient m_tcpClient;
        private CancellationTokenSource m_cancelationSource;

        public Client(string host, uint port, string clientId, uint timeoutMilliseconds)
        {
            m_id = m_lastId++;
            m_host = host;
            m_port = port;
            m_clientId = clientId;
            m_timeoutMilliseconds = timeoutMilliseconds;
            m_tcpClient = null;
            m_cancelationSource = null;
        }

        ~Client()
        {
            Disconnect();
        }

        /// <summary>
        /// Attempts to connect to the hostname and port specified in the constructor
        /// </summary>
        /// <throws cref="System.ApplicationException" on failure
        public void Connect()
        {
            Disconnect();

            m_tcpClient = new TcpClient();
            m_cancelationSource = new CancellationTokenSource();

            try
            {
                m_tcpClient.Connect(m_host, (int)m_port);
            }
            catch (SocketException e)
            {
                string msg = string.Format("Client #{0} failed to connect to {1} on port {2}"
                                          , m_id, m_host, m_port);
                throw new System.ApplicationException(msg, e);
            }

            if (m_tcpClient.Connected)
            {
                log.Debug(string.Format("Client #{0} connnected to the Component on {1}"
                                      , m_id, m_tcpClient.Client.RemoteEndPoint.ToString()));
            }
        }

        public void Disconnect()
        {
            if (m_cancelationSource != null)
            {
                m_cancelationSource.Cancel();

                // TODO - There needs to be some kind of wait here until the async methods all return!
                //        How to do that?
                //        Are we even supposed to be manually canceling? One would think TcpClient.Close takes care of that,
                //        however when deleting all cancelation stuff, instead we get exceptions from the async methods about
                //        using TcpClient's members after it was disposed.

                m_cancelationSource.Dispose();
                m_cancelationSource = null;
            }

            if (m_tcpClient != null)
            {
                m_tcpClient.Close();
                m_tcpClient = null;
            }
        }

        public void Login()
        {
            string loginRequest = string.Format("loginstuff{0}", m_clientId);
            var data = Encoding.ASCII.GetBytes(loginRequest);

            NetworkStream stream = m_tcpClient.GetStream();
            Task writeTask = stream.WriteAsync(data, 0, data.Count());

            // This will block until the login is sent
            // We want block until the login is sent, so we can be sure we logged in before making requests
            if( !writeTask.Wait((int)m_timeoutMilliseconds) )
            {
                // Error - Send timed out
                log.Error(string.Format("Client #{0} Timed out while sending login request to the Component"
                                      , m_id));
            }
            else
            {
                log.Debug(string.Format("Client #{0} sent login request to the Component"
                                       , m_id));
            }
        }

        public async void Read()
        {
            byte[] buffer = new byte[1024];
            MemoryStream memoryStream = new MemoryStream();

            NetworkStream networkStream = m_tcpClient.GetStream();
            Task<int> readTask = null;

            bool disconnected = false;

            try
            {
                while (!disconnected)
                {
                    readTask = networkStream.ReadAsync(buffer, 0, buffer.Length, m_cancelationSource.Token);
                    int bytesReceived = await readTask;

                    if (readTask.Status == TaskStatus.RanToCompletion)
                    {
                        if( bytesReceived <= 0)
                        {
                            disconnected = true;
                            continue;
                        }

                        memoryStream.Write(buffer, 0, bytesReceived);

                        // TODO - Handle parsing of messages in the memory stream

                        memoryStream.Seek(0, SeekOrigin.Begin);
                    }
                    else if (readTask.Status == TaskStatus.Canceled)
                    {
                        // Error - Read was cancelled
                        log.Error(string.Format("Client #{0} Read operation was canceled."
                                              , m_id));
                        disconnected = true;
                        continue;
                    }
                    else
                    {
                        // Error - Unexpected status
                        log.Error(string.Format("Client #{0} Read operation has unexpected status after returning from await."
                                              , m_id));
                    }
                }
            }
            catch (System.Exception e)
            {
                log.Error(string.Format("Client #{0} Exception caught while reading from socket. Exception: {1}"
                                       , m_id, e.ToString()));
            }
        }

        public async void MakeRequest(string thingy)
        {
            string message = string.Format("requeststuff{0}", thingy);
            var data = Encoding.ASCII.GetBytes(message);

            NetworkStream networkStream = m_tcpClient.GetStream();
            Task writeTask = null;

            try
            {
                writeTask = networkStream.WriteAsync(data, 0, data.Count(), m_cancelationSource.Token);
                await writeTask;

                if (writeTask.Status == TaskStatus.RanToCompletion)
                {
                    log.Debug(string.Format("Client #{0} sent request for thingy {1} to the Component"
                                           , m_id, thingy));
                }
                else if (writeTask.Status == TaskStatus.Canceled)
                {
                    // Error - Write was cancelled
                    log.Error(string.Format("Client #{0} Write operation was canceled while requesting thingy {1} from the Component"
                                          , m_id, thingy));
                }
                else
                {
                    // Error - Unexpected status
                    log.Error(string.Format("Client #{0} Write operation has unexpected status after returning from await, while requesting thingy {1} from the Component"
                                          , m_id, thingy));
                }
            }
            catch (System.Exception e)
            {
                log.Error(string.Format("Client #{0} Exception caught while requesting thingy {1}. Exception: {2}" 
                                       , m_id, thingy, e.ToString()));
            }
        }
    }
}

main:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using log4net;
using log4net.Config;

namespace IntegrationTests
{
    class Program
    {
        private static readonly ILog log = LogManager.GetLogger("root");

        static void Main(string[] args)
        {
            try
            {
                XmlConfigurator.Configure();
                log.Info("Starting Component Integration Tests...");

                Client client = new Client("127.0.0.1", 24001, "MyClientId", 60000);
                client.Connect();

                client.Read();
                client.Login();
                client.MakeRequest("Stuff");

                System.Threading.Thread.Sleep(60000);

                client.Disconnect();
            }
            catch (Exception e)
            {
                log.Error(string.Format("Caught an exception in main. Exception: {0}"
                                      , e.ToString()));
            }
        }
    }
}

此行为是 TCP 堆栈的设计使然。看这个帖子 https://github.com/xamarin/xamarin-android/issues/1347#issuecomment-369729481进行解释(xamarin,但同样的原则也适用于此)。 如果您可以控制客户端和服务器,您可以创建一些轮询机制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 NetworkStream.WriteAsync 检测错误 的相关文章

  • 遍历后加快数组查找速度?

    我有一个123MB大的int数组 它基本上是这样使用的 private static int data new int 32487834 static int eval int c int p data c 0 p data p c 1 p
  • 如何使用 LINQ ForEach 更改 List

    我有一个List
  • 求 a 范围内的 pow(a^b)modN

    对于给定的b and N以及一系列a say 0 n 我需要找到ans 0 n 1 where ans i 没有a s为此pow a b modN i 我在这里搜索的是可能的重复pow a b modN对于一系列a 以减少计算时间 例子 i
  • 以编程方式更改 Excel 中的字体(Trebuchet MS、Calibari)C#

    我目前正在使用一个 C 应用程序 该应用程序有一个将生成 Excel 文件的类 一切都很顺利 Excel 工作表上填充的数据具有 Times New Roman 字体 我想将其更改为其他字体 Calibari 我怎样才能以编程方式做到这一点
  • 如何将 CroppedBitmap 转换为 BitmapImage

    我正在尝试将 CroppedBitmap 转换为 BitmapImage 编辑 不使用内存流 我尝试过直接转换它 似乎这不是一个选择 这应该没那么难 我正在尝试剪切 BitmapImage 的一部分 并创建一个仅包含新裁剪的 Bitmap
  • 在异步方法中使用时 HttpClient 标头被清空

    我正在使用 NET Framework 4 6 1 我的 Web api 中有一个控制器 其中有静态 HttpClient 来处理所有 http 请求 在 IIS 上托管我的应用程序后 大约每月一次 我的应用程序的所有传入请求都会出现以下异
  • 外部剃刀视图看不到外部模型

    我对外部剃刀视图有疑问 在我的项目中 我有主 mvc Web 程序集和动态加载的外部类库程序集 来自 DB 及其自己的控制器 视图和模型 这些程序集在运行时不会直接引用和加载 我能够通过为控制器创建自定义控制器工厂 为视图创建自定义虚拟路径
  • MVVM 同步集合

    是否有一种标准化方法可以将 Model 对象集合与 C 和 WPF 中匹配的 ModelView 对象集合同步 我正在寻找某种类 可以使以下两个集合保持同步 假设我只有几个苹果 并且可以将它们全部保存在内存中 换句话说 我想确保如果我将 A
  • 第三方引用的 dll 未被复制来构建

    我有一个第三方 net dll 被我的 dll 类库项目 A 引用和使用 我的控制台应用程序项目 B 引用项目 A 我的问题是第三方 dll 没有被复制到控制台应用程序项目 B 的构建中 这里有什么问题呢 我的 dll 类库中引用的第三方
  • argc 和 argv 在 Windows 中没有用吗?

    在 Linux 中 argc 和 argv 计算终端中的参数 但在 Windows 中 我找不到放置第二个参数的地方 事实上 每次我运行该程序时 它都会创建那个丑陋的黑色窗口 我什至没有机会给出任何争论 那么这两个变量在Windows平台下
  • OpenMP 循环数组访问中的错误共享

    我想利用 OpenMP 来并行执行我的任务 我需要将数组的所有元素减去相同的数量并将结果写入另一个向量中 两个数组都是动态分配的malloc第一个填充了文件中的值 每个元素都有类型uint64 t pragma omp parallel f
  • 内存不足异常

    我正在使用 C 和 asp net 开发一个网络应用程序 我一直收到内存不足的异常 该应用程序的作用是从数据源读取一堆记录 产品 可能是数百 数千 通过向导中的设置处理这些记录 然后使用处理的产品信息更新不同的数据源 虽然有多个 DB 类
  • 如何在Windows Azure上调用ffmpeg.exe转换音频文件?

    我在 Windows Azure 上运行 Web 角色来接收 AAC 音频文件 通过 base64 字符串上传 并将它们存储到 blob 中 现在效果很好 接下来 我还必须将它们转换为 MP3 并将 MP3 存储到 blob 中 我决定使用
  • WPF MVVM后台打印数据绑定问题

    我正在使用 wpf mvvm 开发一个销售点应用程序 在交易生命周期的许多阶段 都会在后台打印收据 我已经使用其他示例在后台生成和打印收据 我正在后台打印一个 UserControl 一切看起来都很棒 然后 我为该控件创建了 ViewMod
  • 简单的喷射器将具体类型与生活方式结合起来

    我正在寻找一种可以使用指定的生活方式注册具体类型的方法 基本上如下所示 public void SomeFunction Type concrete Lifestyle lifestyle gt container Register con
  • 如何在 Windows 8.1 上打开多个 Visual Studio 窗口? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我使用的是 Windows 7 我能够启动多个 Visual Studio 并同时工作 现在我有 Windows 8 1 操作系统 每当我
  • 矩阵行列式算法 C++

    我是编程新手 我一直在寻找一种找到矩阵行列式的方法 我在网上找到了这段代码 但我很难理解这里的算法 我对递归的基础没有问题 但继续和主循环我很难理解 非常感谢任何可以向我解释该算法的人 int determ int a MAX MAX in
  • 使用反射检测属性的访问修饰符类型

    我编写了一些代码来使用反射查看属性 我已经使用反射从类中检索了属性列表 但是我需要查明该财产是公共的还是受保护的 例如 public string Name get set protected int Age get set Propert
  • 预览MouseMove 与 MouseMove

    我有相当多的 XAML 经验 但最近我注意到我的大多数同事都使用预览鼠标移动代替鼠标移动事件 我一直用鼠标移动它对我很有帮助 但我忍不住问我什么时候应该使用预览鼠标移动什么时候鼠标移动 有什么区别 各自有什么优点和缺点等等 PreviewM
  • 如何从与 C# lambda 集成(而非代理集成)的 Amazon API 网关获取正确的 http 状态代码?

    我正在使用 C lambda 与 API 网关集成 我希望 API 网关返回正确的错误代码 例如 400 404 500 等 API网关模块tf文件 provider aws version lt 2 70 0 region var aws

随机推荐

  • 当 WSDL 太大时,JAX-WS 客户端挂起 30 秒

    我对 JAX WS Webservices 和 Apache CXF 有点陌生 我们正在开发一个简单的客户端 服务器系统 它们之间的通信是通过 JAX WS Web 服务协议 在服务器端 我们使用 Apache CXF 实现 因为使用拦截器
  • 为什么这个计算表达式生成器在我的 for 循环中需要“单位”?

    这是一个后续问题这个问题 https stackoverflow com questions 23122639 how do i write a computation expression builder that accumulates
  • 使用 Google Apps 脚本从网页提取数据时的字符编码问题

    我已经使用 Google Apps 脚本编写了一个脚本 将网页中的文本提取到 Google 表格中 我只需要这个脚本来处理特定的网页 因此它不需要是通用的 该脚本几乎完全按照我想要的方式工作 除了我遇到了字符编码问题 我正在提取希伯来语和英
  • 无法读取 null 的属性“setState”

    我正在启动 ReactJS 并尝试使用 Firebase 作为数据库来收集我的数据 我已经被困了 2 天了 原因是这个错误 无法读取 null 的属性 setState 我可以从 Firebase 读取数据 但无法显示它们 我真的不知道该怎
  • @Binds 方法必须只有一个参数,其类型可分配给返回类型

    我正在迁移到新的 dagger android 2 11 所有设置都基于 Google 蓝图 MVP Dagger 但是我遇到了这个错误 错误 22 57 错误 Binds 方法必须只有一个参数 其类型可分配给返回类型 在这一行中 Acti
  • 为什么“this”解析在 JavaScript 中如此特殊?

    警告 首先是有问题的 JavaScript 代码 1 buggy counter problem this can be broken var Counter1 function this count 0 this increment fu
  • 为不同部分设置 rmarkdown 选项卡颜色

    我想用 Rmarkdown 创建一个 html html 应包含彩色选项卡 根据来自的答案这个问题 https stackoverflow com questions 55276670 coloring tabs in rmarkdown我
  • 使用 ELKI 对字符串数据进行聚类

    我需要使用 ELKI 基于编辑距离 编辑距离对大量字符串进行聚类 由于数据集太大 我想避免基于文件的预计算距离矩阵 我怎么能够 a 从文件 仅 标签 加载 ELKI 中的字符串数据 b 实现访问标签的距离函数 扩展 AbstractDBID
  • 在 Web.Scotty 中使用 StateT

    我正在尝试制作一个愚蠢的网络服务器 将数据存储为State 我在用着Web Scotty http hackage haskell org package scotty 我之前用过 ReaderT 和 scotty 来访问配置 https
  • 如何删除“其他用户”可安装触发器?

    有没有办法删除 其他用户 可安装的触发器 足够幸运地猜测要删除哪个用户只会显示他们的触发器已禁用 但仍然需要您登录他们的 Gmail 才能删除它 当您是电子表格的 所有者 时 这有点令人担忧 您无法删除其他用户的触发器 脚本的触发器与用户的
  • 对不同记录进行 PIVOT 查询

    我有下表 Id Code percentage name name1 activity 1 Prashant 43 43 James James Running 1 Prashant 70 43 Sam Sam Cooking 1 Pras
  • JQuery 移动表单在首次查看后丢失格式

    我在 JQuery mobile 中有一个页面 其中包含一个表单 该表单同时具有静态元素 在 html 中定义 和动态元素 在运行时通过脚本创建 我第一次访问我的页面时 它使用 JQuery 移动格式正确呈现 如果我回去 然后再次打开表单
  • Android MVVM startActivity 最佳实践

    我正在使用 MVVM 和 DataBinding 构建 Android 应用程序 我的 ViewModel 中有一个启动 Activity 的函数 在 ViewModel 中进行 onClick 调用可以吗 像这样 public class
  • C# 到 MySQL 服务器的 SSH 隧道

    我正在尝试编写一个简单的程序来连接到只能通过 SSH 连接的 MySQL 远程服务器 它报告 SSH 连接并且端口转发 但随后声明它无法连接到任何指定的主机 我这个配置错了吗 以下是控制台输出和代码 using System using S
  • 单击一个元素突出显示其他元素

    单击另一个元素时有什么方法可以更改元素的属性吗 例如 考虑这种方法 我有一个像这样的链接 a href 100 Click me a 然后接近它我有这个 span class clickTarget Important text span
  • 如何根据 PHP 代码或 URL 方向的变化激活 CSS 属性?

    我使用 PHP 数组更改网站中的语言lang 当用户单击链接来更改网站的语言时 我希望此链接保持 按下 或更改为不同的颜色 以便用户知道他 她所在的网站版本 在这种情况下如何激活 CSS 属性 通用 php
  • 使用 Office Automation 时检查挂起的 Office 进程

    有没有办法在使用 Office Automation 时检查 Microsoft Office 进程 即 Word Excel 是否挂起 另外 如果进程挂起 有没有办法终止它 首先我要说的是 我不建议在服务器上的服务中执行此操作 但我会尽力
  • 在Numpy数组中如何找到一个值的所有坐标

    如果我想找到所有 3D 数组中最大值的坐标 如何找到它们 到目前为止 这是我的代码 但它不起作用 我不明白为什么 s set elements np isnan table numbers table elements biggest fl
  • GDI+支持图形加速吗?

    我正在尝试使用 C 和 Win API 为 Windows 平台编写屏幕保护程序 为了渲染图形 我使用 GDI 但问题是渲染带有少量动画 淡入和淡出 的 png 变得非常 CPU 繁重 所以我想知道是否有办法为 GDI API 启用 GPU
  • 使用 NetworkStream.WriteAsync 检测错误

    如果我在调用后杀死我的服务器Login完成后 调用时不会引发异常stream WriteAsync data 0 data Count 已完成 并且返回的任务中没有错误指示 那么 我应该如何检测错误呢 当然 应该有一些迹象表明我试图通过已挂