一种C# TCP异步编程中遇到的问题
发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发。程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,GP
千家信息网最后更新 2025年01月19日一种C# TCP异步编程中遇到的问题
最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发。
程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,GPRS设备的网络连接十分的不问题,由此会产生不少的"奇怪"问题。
实际过程中,程序运行几个小时后,无线端的socket server断开就再也无法打开。找了很久都没发现。
通过wireshark抓取通信报文,一般是在TCP的三次握手时出的问题。
常规的TCP三次握手,由TCP的标识可简单看作:SYN-SYN ACK-ACK,实际遇到问题时,标识为:SYN-RST ACK。
可以明显看出,服务端发出了重置的标识,用来积极的拒绝了客户端的连接。
程序的server部分代码,采用的常规的TCP异步编程方式,一下是MSDN代码
// This server waits for a connection and then uses asynchronous operations to // accept the connection with initial data sent from the client. // Establish the local endpoint for the socket. IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); // Bind the socket to the local endpoint, and listen for incoming connections. listener.Bind(localEndPoint); listener.Listen(100); while (true) { // Set the event to nonsignaled state. allDone.Reset(); // Start an asynchronous socket to listen for connections and receive data from the client. Console.WriteLine("Waiting for a connection..."); // Accept the connection and receive the first 10 bytes of data. // BeginAccept() creates the accepted socket. int receivedDataSize = 10; listener.BeginAccept(null, receivedDataSize, new AsyncCallback(AcceptReceiveDataCallback), listener); // Wait until a connection is made and processed before continuing. allDone.WaitOne(); } } public static void AcceptReceiveDataCallback(IAsyncResult ar) { // Get the socket that handles the client request. Socket listener = (Socket) ar.AsyncState; // End the operation and display the received data on the console. byte[] Buffer; int bytesTransferred; Socket handler = listener.EndAccept(out Buffer, out bytesTransferred, ar); //再次投递接收,实现一直接收socket的操作 listener.BeginAccept(null, receivedDataSize, new AsyncCallback(AcceptReceiveDataCallback), listener); }
经过问题的定位,可以判断可能是程序的异步接收回调中出了问题,但实际添加调试信息后发现,在程序出现端口无法打开后,再进行回调函数操作,并无信息打出。
TCP异步编程,一般是成对的出现beginXXX...endXXX,再通过回调函数进行具体处理。
如下为accept的回调函数,代码中使用了try..catch来捕获异常,实际问题可能就出在这里,代码如下:
public static void AcceptReceiveDataCallback(IAsyncResult ar) { // Get the socket that handles the client request. Socket listener = (Socket) ar.AsyncState; // End the operation and display the received data on the console. byte[] Buffer; int bytesTransferred; try{ Socket handler = listener.EndAccept(out Buffer, out bytesTransferred, ar); } catch(异常1 e){ ... return; } catch(异常2 e){ ... return; } //再次投递接收,实现一直接收socket的操作 listener.BeginAccept(null, receivedDataSize, new AsyncCallback(AcceptReceiveDataCallback), listener); }
程序在实际出现端口不能打开之前曾经进入过"异常1"/"异常2",判断很可能是程序进行了return,而无法再次投递接收操作。
此时所有的端口打开操作,都会进入socket.listen(backlog)的队列中,当accpet队列中的内容无法通过完整begin..end操作取出,队列满后socket的底层协议栈则会拒绝新的socket连入。
程序
问题
实际
代码
再次
函数
标识
端口
队列
服务
编程
信息
工具
常规
端的
设备
运行
明显
众所周知
一端
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
台湾服务器游戏虚拟主机
潮州原生影视软件开发
qq的数据库在哪儿
菜籽互联网科技媒体
苏州网站建设软件开发
重庆crm软件开发服务费
pg数据库怎么删某一条数据
美创科技网络安全产业链图谱
怎么解决多线程访问数据库
数据库账户保密
我的世界起床服务器ip
解压之后怎么保存数据库
庆余年官服服务器
重庆联想服务器
神武服务器人数
个人软件开发服务费税率
家庭网络技术基础详解
榆林5g软件开发工程师
771 服务器
网络安全攻防大赛解析
南京千度软件开发
大数据时代网络安全分析
服务器root密码
中学开展网络安全专题教育视频
2020网络安全法相关论文
oracle 数据库整理
小枫免流量服务器软件
软件开发对显卡要求高吗
s开头的内存数据库
苹果APP更新软件开发者