在C#中利用Keep-Alive处理Socket网络异常断开的方法 (转)
最近我负责一个IM项目的开发,服务端和客户端采用TCP协议连接。服务端采用C#开发,客户端采用Delphi开发。在服务端开发中我碰到了各种各样的网络异常断开现象。在处理这些异常的时候有了一些心得,现在写出来和大家分享一下。
那网络异常断开原因主要有那些呢?归纳起来主要有以下两种:
1、客户端程序异常。
对于这种情况,我们很好处理,因为客户端程序异常退出会在服务端引发ConnectionReset的Socket异常(就是WinSock2中的10054异常)。只要在服务端处理这个异常就可以了。
2、网络链路异常。
如:网线拔出、交换机掉电、客户端机器掉电。当出现这些情况的时候服务端不会出现任何异常。这样的话上面的代码就不能处理这种情况了。对于这种情况在MSDN里面是这样处理的,我在这里贴出MSDN的原文:
如果您需要确定连接的当前状态,请进行非阻止、零字节的 Send 调用。如果该调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035),则该套接字仍然处于连接状态;否则,该套接字不再处于连接状态。
但是我在实际应用中发现,MSDN说的这种处理方法在很多时候根本无效,无法检测出网络已经异常断开了。那我们该怎么办呢?
我们知道,TCP有一个连接检测机制,就是如果在指定的时间内(一般为2个小时)没有数据传送,会给对端发送一个Keep-Alive数据报,使用的序列号是曾经发出的最后一个报文的最后一个字节的序列号,对端如果收到这个数据,回送一个TCP的ACK,确认这个字节已经收到,这样就知道此连接没有被断开。如果一段时间没有收到对方的响应,会进行重试,重试几次后,向对端发一个reset,然后将连接断掉。
在Windows中,第一次探测是在最后一次数据发送的两个小时,然后每隔1秒探测一次,一共探测5次,如果5次都没有收到回应的话,就会断开这个连接。但两个小时对于我们的项目来说显然太长了。我们必须缩短这个时间。那么我们该如何做呢?我要利用Socket类的IOControl()函数。我们来看看这个函数能干些什么:
使用 IOControlCode 枚举指定控制代码,为 Socket 设置低级操作模式。
命名空间:System.Net.Sockets
程序集:System(在 system.dll 中)
语法
C#
public int IOControl (
IOControlCode ioControlCode,
byte[] optionInValue,
byte[] optionOutValue
)
参数
ioControlCode
一个 IOControlCode 值,它指定要执行的操作的控制代码。
optionInValue
Byte 类型的数组,包含操作要求的输入数据。
optionOutValue
Byte 类型的数组,包含由操作返回的输出数据。
返回值
optionOutValue 参数中的字节数。
如:
我们要搞清楚的就是inOptionValues的定义,在C++里它是一个结构体。我们来看看这个结构体:
...{
u_long onoff; //是否启用Keep-Alive
u_long keepalivetime; //多长时间后开始第一次探测(单位:毫秒)
u_long keepaliveinterval; //探测时间间隔(单位:毫秒)
};
在C#中,我们直接用一个Byte数组传递给函数:
byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);//是否启用Keep-Alive
BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));//多长时间开始第一次探测
BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);//探测时间间隔
具体实现代码:
...{
Thread.CurrentThread.IsBackground = true;
while (true)
...{
uint dummy = 0;
byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
try
...{
Accept(inOptionValues);
}
catch ...{ }
}
}
private static void Accept(byte[] inOptionValues)
...{
Socket socket = Public.s_socketHandler.Accept();
socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
UserInfo info = new UserInfo();
info.socket = socket;
int id = GetUserId();
info.Index = id;
Public.s_userList.Add(id, info);
socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);
}
好了,这样就成功了。
转载于:https://www.cnblogs.com/jambol/archive/2007/07/31/837946.html
在C#中利用Keep-Alive处理Socket网络异常断开的方法 (转)相关推荐
- 在C#中利用Keep-Alive处理Socket网络异常断开的方法
最近我负责一个IM项目的开发,服务端和客户端采用TCP协议连接.服务端采用C#开发,客户端采用Delphi开发.在服务端开发中我碰到了各种各样的网络异常断开现象.在处理这些异常的时候有了一些心得,现在 ...
- MVC中利用ViewBag传递Json数据时的前端处理方法
** MVC中利用ViewBag传递Json数据时的前端处理方法 ** 用viewBag传递Json字符串到前端时,json字符串中的"会被转义为& quot,前端处理方法为@Htm ...
- JQuery中使用Ajax赋值给全局变量失败异常的解决方法,jqueryajax
我们在用JQuery的Ajax从后台提取数据后想把它赋值给全局变量,但是却怎么都赋不进,为什么呢? 原因其实很简单,我们用的Ajax是异步操作,也就是说在你赋值的时候数据还没提取出来,你当然赋不进去, ...
- 常见的Socket网络异常场景分析
原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 在目前微服务的背景下,网络异常越来越常见了,而有一些网络异常非常模糊,理解什么情况下会导致什么异常,还是有一定难度 ...
- python中语法错误-Python语法错误与异常及异常处理方法
回顾 在Python进阶记录之基础篇(二十)中,我们介绍了Python面向对象中的类方法和静态方法,以及类中拥有特殊功能的魔法函数.需要重点掌握类方法和静态方法的概念和基本用法,理解魔法函数的作用冰女 ...
- CTF pwn中利用pwntools加载不同版本libc调试程序的方法
在网上找到了很多加载libc的帖子,终于自己走通了一次,现在把方法和资源都整理一下 一.解决方案 python利用pwntools的代码 from pwn import * import pwnlib ...
- android+网络下载资源,【已解决】Android中利用HttpClient等库实现网络文件下载
[问题] 已经获得了Songtaste中歌曲的地址,比如: 中的真实下载地址是: 然后现在想要去下载这样的文件到Android手机的本地某个文件夹中. [解决过程] 1.其中,关于自动处理Cookie ...
- 使用SQLDMO中“接口SQLDMO.Namelist 的 QueryInterface 失败”异常的解决方法
SQLDMO(SQL Distributed Management Objects,SQL分布式管理对象),它封装 Microsoft SQL Server 数据库中的对象.它允许我们通过COM对象, ...
- python中exception类的_Python自定义一个异常类的方法
如何实现自定义一个异常 python内置了许多异常类,为编写代码划定红线,才使调试代码时能及时发现错误.那么我们编写一个模块也可以为使用此模块者划定红线,来约束使用者可用哪些数据,这就需要自定义异常类 ...
- KDD CUP 99利用决策分类树进行网络异常检测
import pandas as pd import numpy as np import matplotlib.pyplot as plt 数据导入与数据探索 数据导入 df=pd.read_csv ...
最新文章
- 专家解读下一代互联网创新模式,核心技术是根本
- Entity Framework 6 Recipes 2nd Edition(10-3)译 - 返回结果是一个标量值
- Too Many Segments (easy version) CodeForces - 1249D1(贪心+差分)
- nhinx php 调优,高流量站点NGINX与PHP-fpm配置优化
- 简单使用AutoMapper实现DTO转换
- python怎么建立替换_Python-如何搜索和替换文件中的文本?
- Hadoop hdfs上传文件报错解决
- Entity Framework 与 面向对象
- 把代码写成艺术,真正体会面向对象编程思想
- 数据库系统工程师教程 (第三版)前言
- WAPI在校园网应用中的证书安装
- 飞机加油游戏 --- 我的易术
- JAVA算法:三角形周长(JAVA版本算法)
- 一款令人发指的Linux监控软件
- Python 实战案例--计算圆、矩形的周长和面积
- Codeforces 513F1 513F2 Scaygerboss 网络流
- 职场,社恐的终极噩梦
- 第十三次CCF认证经历
- 同方TF32A09加密芯片算法参数
- c语言水仙花数256,c语言学习:求水仙花数
热门文章
- 医疗健康领域的短文本解析探索----文本纠错
- 原价399,限时1元!7天人工智能入门训练营:带你从0掌握机器学习算法!
- 一文总结熵,交叉熵与交叉熵损失
- 百面机器学习—11.集成学习(GBDT、XGBoost)面试问题总结
- 机器学习算法基础6-模型保存与加载、逻辑回归、Kmeans(聚类)
- pytorch之深度学习
- C语言手写模拟字符串String类
- 豆瓣评分9.3的经典Kubernetes图书推出中文版,学习K8S更方便了
- 博文视点新书快讯第78期
- DLL load failed: 找不到指定模块\Failed to load the native TensorFlow runtime解决方法