Unity安卓设备获取NetworkStream的ReadTimeout时出现mono-io-layer-error(10022)的原因
问题分析与解决
问题背景
在Unity项目中,部分安卓设备获取NetworkStream对象的ReadTimeout属性时,会抛出System.Net.Sockets.SocketException异常,错误消息为mono-io-layer-error (10022),多数安卓设备无此问题。
异常堆栈信息:
[Message]: mono-io-layer-error (10022) [Type]: System.Net.Sockets.SocketException [StackTrace]: at System.Net.Sockets.Socket.GetSocketOption (System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName) [0x00000] in <00000000000000000000000000000000>:0 at System.Net.Sockets.NetworkStream.get_ReadTimeout () [0x00000] in <00000000000000000000000000000000>:0
涉及代码片段:
public static byte[] ReadAByteCluster(Stream str, int count) { int timeout = str.CanTimeout ? str.ReadTimeout : 20000; TheRestofThecode(); }
原因分析
错误码10022对应无效参数,本质是部分安卓设备的底层Socket实现不支持读取SO_RCVTIMEO选项(ReadTimeout属性内部通过调用Socket.GetSocketOption获取该值),导致Mono层抛出异常。CanTimeout返回true仅表示流理论上支持超时机制,但实际底层可能不支持读取该属性值。
解决方案
方案1:捕获异常并使用默认超时
在获取ReadTimeout时捕获异常, fallback到预设的默认超时值:
public static byte[] ReadAByteCluster(Stream str, int count) { int timeout = 20000; // 默认超时时间 if (str.CanTimeout) { try { timeout = str.ReadTimeout; } catch (System.Net.Sockets.SocketException) { // 捕获不支持该操作的异常,直接使用默认值 } } TheRestofThecode(); }
方案2:直接操作底层Socket设置超时(若能获取Socket实例)
如果NetworkStream由你自行创建的Socket生成,可直接操作Socket设置超时,避免通过NetworkStream读取属性:
// 假设已创建Socket实例socket socket.ReceiveTimeout = 20000; // 直接设置读取超时 NetworkStream stream = new NetworkStream(socket); // 后续使用stream时,无需再读取ReadTimeout,直接使用预设值即可
方案3:安卓平台针对性处理
针对安卓平台直接跳过读取ReadTimeout逻辑,使用默认超时:
public static byte[] ReadAByteCluster(Stream str, int count) { int timeout = 20000; #if UNITY_ANDROID // 安卓平台直接用默认值,避免触发异常 #else if (str.CanTimeout) { timeout = str.ReadTimeout; } #endif TheRestofThecode(); }
内容的提问来源于stack exchange,提问作者Dadkhah Dadkhah
相关产品推荐
相关产品推荐

