HarmonyOS 鸿蒙Next中求助:使用TCP连接服务器报错 Operation in progress

HarmonyOS 鸿蒙Next中求助:使用TCP连接服务器报错 Operation in progress 调用connect,报错{“code”:2301115,“message”:“Operation in progress”}

不是服务器问题,因为其它语言正常连接

另外error回调中code为0表示什么意思

9 回复

开发者您好,
本地测试暂未复现,能否提供可以复现的demo、SDK、IDE版本,
code为0一般为正常的标志,但是error中暂时未复现该问题
测试SDK 6.1.0,测试代码:

import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG = 'TCP_CLIENT';
const DOMAIN = 0x0000;

class SocketInfo {
  public message: ArrayBuffer = new ArrayBuffer(1);
  public remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}

@Entry
@Component
struct Index {
  // 持有 tcp 实例
  private tcpClient: socket.TCPSocket | null = null;

  // 初始化并连接 TCP
  private connectToServer() {
    // 创建 TCPSocket 实例
    this.tcpClient = socket.constructTCPSocketInstance();

    // 订阅相关事件(接收数据、连接关闭、错误回调)
    this.bindEvents();

    // 绑定本地地址和端口(必须先绑定,可以绑定 0 端口让系统自动分配)
    let bindAddress: socket.NetAddress = {
      address: '0.0.0.0',
      port: 0,
      family: 1
    };

    this.tcpClient.bind(bindAddress).then(() => {
      hilog.info(DOMAIN, TAG, 'Bind success. Connecting...');

      // 连接远端服务器(请替换为你的服务器 IP 和端口)
      let connectAddress: socket.NetAddress = {
        address: '127.0.0.1', // 服务器 IP
        port: 8888,               // 服务器端口
        family: 1
      };

      return this.tcpClient?.connect({ address: connectAddress, timeout: 6000 });
    }).then(() => {
      hilog.info(DOMAIN, TAG, 'Connect success.');
    }).catch((err: BusinessError) => {
      hilog.error(DOMAIN, TAG, `Connect failed. Code: ${err.code}, Message: ${err.message}`);
    });
  }

  // 绑定事件监听
  private bindEvents() {
    if (!this.tcpClient) return;

    this.tcpClient.on('message', (value: SocketInfo) => {
      hilog.info(0x0000, 'testTag', 'on message');
      let buffer = value.message;
      let dataView = new DataView(buffer);
      let str = '';
      for (let i = 0; i < dataView.byteLength; ++i) {
        str += String.fromCharCode(dataView.getUint8(i));
      }
      hilog.info(0x0000, 'testTag', 'on connect received:' + str);
    });

    // 监听连接关闭事件
    this.tcpClient.on('close', () => {
      hilog.info(DOMAIN, TAG, 'Connection closed.');
    });

    // 监听错误事件
    this.tcpClient.on('error', (err: BusinessError) => {
      hilog.error(DOMAIN, TAG, `Socket error: ${err.message}`);
    });
  }

  // 发送数据方法
  private sendData(message: string) {
    if (!this.tcpClient) {
      hilog.error(DOMAIN, TAG, 'Socket is not initialized.');
      return;
    }

    this.tcpClient.send({ data: "123" }).then(() => {
      hilog.info(DOMAIN, TAG, 'Send data success.');
    }).catch((err: BusinessError) => {
      hilog.error(DOMAIN, TAG, `Send failed: ${err.message}`);
    });
  }

  build() {
    Column({ space: 20 }) {
      Button("Connect to Server").onClick(() => {
          this.connectToServer();
        })

      Button("Send Message")
        .onClick(() => {
          this.sendData("Hello HarmonyOS NEXT");
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

服务端代码:

import socket


def start_server(host='127.0.0.1', port=8888):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        # 绑定地址和端口
        s.bind((host, port))

        # 开始监听 (backlog=5 表示最多等待 5 个排队连接)
        s.listen(5)
        print(f"服务端已启动,正在监听 {host}:{port} ...")

        # 接受连接
        conn, addr = s.accept()
        with conn:
            print(f"已连接到客户端: {addr}")

            while True:
                # 接收数据 (最大接收 1024 字节)
                data = conn.recv(1024)
                if not data:
                    print("客户端已断开连接。")
                    break

                message = data.decode('utf-8')
                print(f"收到消息: {message}")

                # 回显消息
                response = f"服务端收到: {message}"
                conn.sendall(response.encode('utf-8'))


if __name__ == "__main__":
    try:
        start_server()
    except KeyboardInterrupt:
        print("\n服务端已停止。")
    except Exception as e:
        print(f"发生错误: {e}")

排查方案:

  • 远端服务器的ip和端口是否正确设置
  • 是否重复调用了 connect
  • 路由器是否存在网络隔离
  • 更新最新版本
  • 提高超时时间

更多关于HarmonyOS 鸿蒙Next中求助:使用TCP连接服务器报错 Operation in progress的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


可以试试调整 timeout 连接超时,我调用AI的接口也是经常因为返回时间太长出错,30秒不够就调到1分钟。特别是生图的模型API

鸿蒙Socket的默认连接超时时间可能较短,如果网络环境稍有延迟,就会触发 EINPROGRESS 错误。

tcp.connect({
    address: connectAddress,
    timeout: 30000 // 将超时时间提高到30秒,给连接更多时间
}, (err: BusinessError) => {
    // ...
});

“code”:2301115,“message”:"Operation in progress"这个是连续调用了 connect() 方法的报错。你估计重复连接了。

至于你说的error code:0 就是表示正常关闭的意思,这个不是错误的。

详细的你可以把代码贴一下,看一下你错在哪里

这个报错:

{"code":2301115,"message":"Operation in progress"}

一般不是服务器异常,而是 Socket 还处于异步连接过程中,你又重复调用了 connect。

HarmonyOS NEXT 的 TCP Socket 是异步非阻塞的,connect() 发起后不会立刻完成。

如果连接还没完成时再次调用 connect(),就会抛:

Operation in progress

常见触发场景:

1、重复调用 connect

比如:

socket.connect(...)
socket.connect(...)

或者按钮连续点击触发多次。


2、没等 connect 成功回调就发送/重连

应该等:

  • connect success
  • on(‘connect’)

之后再 send。

不要直接:

connect()
send()

3、上一次连接没 close

连接状态还没释放,又重新 connect。

先:

socket.close()

再重建 socket。


建议加连接状态保护:

if (this.isConnecting || this.isConnected) {
  return;
}

this.isConnecting = true;

成功 / 失败后重置。


至于:

error 回调中 code = 0 是什么意思?

在 HarmonyOS 网络 API 里,code=0 通常表示:

底层没有明确的系统错误码返回

属于泛化错误 / 未细分错误。

一般结合 message 判断。

比如:

  • 参数异常
  • 状态机错误
  • 回调时序问题

都可能看到 code=0。


重点排查:

如果其它语言正常,而鸿蒙报这个错,优先看是不是代码里有类似:

aboutToAppear() -> connect()
onClick() -> connect()
onReconnect() -> connect()

导致多次并发连接。

一句话:

2301115 = connect 正在执行中,你重复发起了连接;code=0 通常表示无具体底层错误码,重点检查是否重复调用 connect 或未等待异步连接完成。

1、参考这个问答,端口号传数值类型

cke_232.png

2、检查网络权限是否申请:

{
  "module": {
    // ...
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

“Operation in progress” 错误的本质:这个错误表示 connect() 操作正在进行中,但尚未完成。

可能的原因是:

  1. 非阻塞模式下的正常行为。HarmonyOS 的 TCP Socket 默认是非阻塞的,connect() 调用后立即返回,连接在后台进行如果在连接完成前就进行操作,会报此错误。
  2. 重复调用 connect。在前一次 connect 未完成时,再次调用 connect,常见于重试逻辑不当
  3. 未等待连接完成就发送数据。
  4. 回调处理不当。没有正确区分"连接进行中"和"连接失败"

推荐的连接方式,使用 Promise 方式连接

import socket from '@ohos.net.socket';

async function connectToServer(): Promise<void> {
  let tcpSocket = socket.constructTCPSocketInstance();
  
  try {
    // ✅ 订阅连接成功事件
    tcpSocket.on('connect', () => {
      console.info('Connection established succ');
      
      // 连接成功后才能发送数据
      tcpSocket.send({
        data: 'Hello Server'
      }).then(() => {
        console.info('Data sent succ');
      }).catch((err) => {
        console.error('Send failed:', err);
      });
    });
    
    // ✅ 订阅错误事件
    tcpSocket.on('error', (err) => {
      console.error('Socket error:', err);
    });
    
    // ✅ 使用 Promise 方式连接
    await tcpSocket.connect({
      address: {
        address: '192.168.1.100',
        port: 8080,
        family: 1 // 1: IPv4, 2: IPv6
      },
      timeout: 5000 // 超时时间(毫秒)
    });
    
    console.info('Connect call completed');
    
  } catch (err) {
    console.error('Connect failed:', JSON.stringify(err));
  }
}

该错误常见于非阻塞TCP连接场景。在鸿蒙Next中,connect()返回EINPROGRESS表示连接操作已发起但尚未完成。需通过select()poll()监听socket可写事件,完成后调用getsockopt(SO_ERROR)检查连接是否成功。若最终确认失败,可能是网络配置、目标主机不可达或端口未监听导致。

鸿蒙 socket 错误码 2301115 对应 POSIX 的 EINPROGRESS (115),表示操作正在进行中。这通常是 socket 被设置为非阻塞模式时,connect() 调用立即返回,实际连接尚未完成,需等待后续可写事件才能确认连接成功。其他语言默认阻塞模式,所以没有该问题。

处理方式

  • 将 socket 改为阻塞模式再调用 connect,或在非阻塞模式下通过 on('connect') 或监听可写事件判断连接结果。
  • 确保在调用 connect 前未提前设置 socket.setBlocking(false)(默认为 true)。

error 回调 code 为 0: 在鸿蒙 socket 中,error 回调的 code=0 通常表示连接正常关闭(如对端主动断开)或无错误,并非真正的异常。可结合 message 字段处理,若为 "Operation in progress" 则是非阻塞连接中的正常状态,不是故障。

回到顶部