一种C# TCP异步编程中遇到的问题
发表于:2024-10-21 作者:千家信息网编辑
千家信息网最后更新 2024年10月21日,最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发。程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,GP
千家信息网最后更新 2024年10月21日一种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安全错误
数据库的锁怎样保障安全
应用软件开发培训老师
格力软件开发是哪个部门
服务器恢复出厂设置后怎么还原
软件开发员工协议
共享办公管理服务器
网络安全应急预案街道
国家网络安全学院怎么考
数据库软件技术支持
es数据库如何授权访问
手机无法连接到服务器(1
如何登陆挂在远端服务器上的软件
网络安全清查总结
宝塔搭建局域网服务器
日志 存储 数据库
怀旧服pvp服与普通服务器
广西理工计算机网络技术清考
谦奕软件开发有限公司
在软件开发中线程的作用
江西项目管控软件开发平台
温州应用软件开发定做价格
网银互联网科技有限公司
国家网络安全学院怎么考
数据库类型 time
node云服务器
lol各个区服务器
vb和数据库的连接数据库
购物车存在到数据库吗
中国首个儿童遗传性肾病数据库
妖精的尾巴手游服务器怎么进去
学网络技术吃香