AsyncSocket

立即使用

概述

什么是Socket?

两个程序通过一个双向通信连接实现数据交互,这个连接就叫Socket。是网络模型中应用层与TCP/IP协议簇通信的中间软件抽象层,即对TCP/IP进行封装的一套API。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。socket可以支持不同的传输协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接;同理,当使用UDP协议进行连接时,该Socket连接就是一个UDP连接。

Socket 通信逻辑流程:

1)服务端利用Socket监听端口;

2)客户端发起连接;

3)服务端返回信息,建立连接,开始通信;

4)客户端/服务端断开连接。

什么是粘包?

Socket 通讯是先将数据存放到缓冲区,然后发送到接受端的缓冲区,接收方再读取缓冲区的数据包。由于传输的过程为数据流,经过TCP传输后,三条数据被合并成了一条,这就是数据粘包。因为TCP使用了优化方法(Nagle算法)。它将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这么做优点也很明显,就是为了减少广域网的小分组数目,从而减小网络拥塞的出现。而UDP就不会有这种情况,它不会使用块的合并优化算法。当然除了优化算法,TCP和UDP都会因为下面两种情况造成粘包:1.发送端需要等缓冲区满才发送出去,造成粘包;2.接收方不及时接收缓冲区的包,造成多个包接收。

什么是断包?

断包应该还是比较好理解的,其原理同粘包。

模块概述

本模块封装了 Socket 相关功能接口,是建立的基于TCP的链接。可通过 startServer/stopServer 创建/停止服务端,客户端通过 connectServer 接口链接服务端,serverDisonnectListener可监听同服务端链接断开事件。服务端通过 clientConnectListener 监听客户端链接断开事件。serverReceiveDataListener、clientReceiveDataListener可分别监听对端发送过来的消息。本模块支持发送字符串消息,也支持发送各种类型的文件:pdf、txt、docx、ppt、mp3、mp4、png、jpeg等。

本模块是单例模式,在全局任何地方调用本模块都是同一个 socket 的实例对象。

本模块对粘包的解决方案

针对 Socket 粘包问题,本模块的处理逻辑:每次发送数据时,模块给数据封包,添加一个包头,在包头和包体之间设置一个分割符。收到数据后再进行拆包,拆包是按规定好的分割符进行拆包的。包头格式如下:

{
     'type':'file',         //字符串类型;file|string,发送的数据的类型,支持文件或字符串
     'size':'10240',        //字符串类型;发送的数据的大小,单位B
     'fileName':'test.png'. //字符串类型;发送文件时,文件的名,发送字符串时本参数无意义
}

模块会自动识别数据的大小,生成一个包头(标准的 JSON 字符串),然后将包头和数据以及分割符转化成二进制数据并按照【包头分割符数据】的格式拼接。模块发送该封装好的数据包,Socket 会按照自己的逻辑粘包或者断包发送至对端缓冲区。对端先按照预设的分割符从缓冲区读取包头,提取包体 size 大小,然后再按 size 从缓冲区读取包体。此时得到的数据是二进制数据,模块再将之转化为原来的类型(字符串或文件)回调给前端开发者。

接口

startServer

开启服务

startServer({params}, callback(ret, err))

params

charset:

  • 类型:字符串
  • 描述:(可选项)编码格式,仅支持 Android 平台,iOS仅支持UTF-8
  • 默认值:‘UTF-8’

port:

  • 类型:数字
  • 描述:(可选项)端口号
  • 默认值:2199

decollator:

  • 类型:字符串
  • 描述:(可选项)包头和包体数据之间的分割符
  • 默认值:\r\n

callback(ret, err)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
   status: true        //布尔类型;服务创建是否成功
}

err:

  • 类型:JSON 对象
  • 内部字段:
{
   msg:''              //字符串类型;开启服务失败信息
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.startServer({
    port:3445
},function(ret, err) {
    if (ret.status) {
        console.log(JSON.stringify(ret));
    } else {
        console.log(JSON.stringify(err));
    }
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

stopServer

停止服务

stopServer()

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.stopServer();

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

isClientConnected

目标客户端是否已经链接

isClientConnected({params},callback(ret))

params

IP:

  • 类型:字符串
  • 描述:目标客户端的 IP 地址

port:

  • 类型:数字
  • 描述:目标客户端的端口号

callback(ret)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    isConnected: true    //布尔类型;是否链接
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.isClientConnected({
    IP:'172.20.10.1',
    port:3445
},function(ret) {
   console.log(JSON.stringify(ret));
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

isClientDisconnected

目标客户端是否已断开链接

isClientDisconnected({params},callback(ret))

params

IP:

  • 类型:字符串
  • 描述:目标客户端的 IP 地址

port:

  • 类型:数字
  • 描述:目标客户端的端口号

callback(ret)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    isDisconnected: true    //布尔类型;是否断开链接
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.isClientDisconnected({
    IP:'172.20.10.1',
    port:3445
},function(ret) {
   console.log(JSON.stringify(ret));
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

getAddress

获取接收 IP 和端口号

getAddress(callback(ret, err))

callback(ret, err)

ret:

  • 类型:JSON 对象
  • 描述:获取的地址信息
  • 内部字段:
{
    status: true ,     //布尔类型;true|false
    IP:'',             //字符串类型;服务链接ip  
    port:80            //数字类型;服务端口号  
}

err:

  • 类型:JSON 对象
  • 内部字段:
{
    msg:''              //字符串类型;错误信息
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.getAddress(function(ret,err){
    if (ret.status) {
        console.log(JSON.stringify(ret));
    } else {
        console.log(JSON.stringify(err));
    }
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

clientConnectListener

监听有客户端连接事件

clientConnectListener(callback(ret))

callback(ret, err)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    eventType:'',     //字符串类型;交互事件类型;取值范围:
                      //connect:链接事件
                      //disconnect:断开链接事件 (android不支持)
    IP:'',            //字符串类型;客户端地址
    port:             //数字类型;客户端端口号
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.clientConnectListener(function(ret){
    api.alert({msg:JSON.stringify(ret)});
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

serverReceiveDataListener

监听客户端发送来数据的事件

serverReceiveDataListener(callback(ret))

callback(ret, err)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    eventType:'',     //字符串类型;交互事件类型;取值范围:
                      //err:接受数据时发生错误
                      //receiveString:接收到字符串
                      //receiveFile:接收到文件
    IP:'',            //字符串类型;客户端地址
    port:             //数字类型;客户端端口号
    filePath:         //字符串类型;文件路径,仅当receiveFile时有值
    string:           //字符串类型;收到的字符串,仅当receiveString时有值
}

err:

  • 类型:JSON 对象
  • 内部字段:
{
    msg:''           //字符串类型;错误信息
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.serverReceiveDataListener(function(ret){
    api.alert({msg:JSON.stringify(ret)});
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

sendToClient

发送数据到客户端

sendToClient({params})

params

data:

  • 类型:字符串
  • 描述:发送的字符串,如果是文件则传文件路径(本地路径)

type:

  • 类型:字符串
  • 描述:(可选项)发送到数据类型
  • 默认:string
  • 取值范围:
    • string:字符串
    • file:文件

decollator:

  • 类型:字符串
  • 描述:(可选项)发送数据时封包的包头和包体分割符,
  • 注意:要跟客户端connectServer接口传入的一致
  • 默认:\r\n

IP:

  • 类型:字符串
  • 描述:目标客户端的 IP 地址

port:

  • 类型:数字
  • 描述:目标客户端的端口号

callback(ret, err)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    eventType:'',    //字符串类型;交互事件类型;取值范围:
                     //error:发生错误
                     //complete:发送完成
                     //sending:发送中
    partialLength:   //数字类型;发送进度;仅当 sending 时有值
}

err:

  • 类型:JSON 对象
  • 内部字段:
{
   msg:''          //字符串类型;错误信息
}

示例代码

var ArgFace = api.require('AsyncSocket');
ArgFace.sendToClient({
    data:'123456',
    IP:'172.20.10.1',
    port:3445
},function(ret,err){
    api.alert({msg:JSON.stringify(ret)});
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

connectServer

链接服务端

connectServer({params})

params

IP:

  • 类型:字符串
  • 描述:要断开的客户端的 IP 地址

port:

  • 类型:数字
  • 描述:要断开的客户端的端口号

decollator:

  • 类型:字符串
  • 描述:(可选项)包头和包体数据之间的分割符
  • 默认值:\r\n

callback(ret, err)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    status: true,   //布尔类型;true|false,操作是否成功
    IP:'',          //字符串类型;本地IP地址
    port:           //数字类型;本地和服务器通信的端口号
}

err:

  • 类型:JSON 对象
  • 内部字段:
{
   msg:''          //字符串类型;错误信息
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.connectServer({
    IP:'172.20.10.10',
    port:3445
},function(ret, err) {
    if (ret.status) {
        console.log(JSON.stringify(ret));
    } else {
        console.log(JSON.stringify(err));
    }
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

disconnectServer

断开链接服务端

disconnectServer()

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.disconnectServer( );

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

isServerConnected

是否已跟服务端链接

isServerConnected(callback(ret))

callback(ret)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    isConnected: true    //布尔类型;是否链接
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.isServerConnected(function(ret) {
   console.log(JSON.stringify(ret));
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

isServerDisconnected

是否跟服务端端开链接

isServerDisconnected(callback(ret))

callback(ret)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    isDisconnected: true    //布尔类型;是否断开链接
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.isServerDisconnected(function(ret) {
   console.log(JSON.stringify(ret));
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

serverDisonnectListener

监听与服务端断开链接 (Android暂不支持)

serverDisonnectListener()

callback()

只有回调函数执行,无参数回调

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.serverDisonnectListener(function(ret){
    api.alert({msg:JSON.stringify(ret)});
});

可用性

iOS 系统

可提供的 1.0.0 及更高版本

clientReceiveDataListener

客户端收到消息监听

clientReceiveDataListener(callback(ret))

callback(ret, err)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    eventType:'',     //字符串类型;交互事件类型;取值范围:
                      //err:接受数据时发生错误
                      //receiveString:接收到字符串
                      //receiveFile:接收到文件
    IP:'',            //字符串类型;服务端地址
    port:             //数字类型;服务端端口号
    filePath:         //字符串类型;文件路径,仅当receiveFile时有值
    string:           //字符串类型;收到的字符串,仅当receiveString时有值
}

err:

  • 类型:JSON 对象
  • 内部字段:
{
    msg:''           //字符串类型;错误信息
}

示例代码

var AsyncSocket= api.require('AsyncSocket');
AsyncSocket.clientReceiveDataListener(function(ret){
    api.alert({msg:JSON.stringify(ret)});
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本

sendToServer

发送数据到服务端

sendToServer({params})

params

data:

  • 类型:字符串
  • 描述:发送的字符串,如果是文件则传文件路径(本地路径)

type:

  • 类型:字符串
  • 描述:(可选项)发送到数据类型
  • 默认:string
  • 取值范围:
    • string:字符串
    • file:文件

decollator:

  • 类型:字符串
  • 描述:(可选项)发送数据时封包的包头和包体分割符,(Android 可以为一个特殊字符)
  • 注意:要跟服务端startServer接口传入的一致
  • 默认:\r\n

callback(ret, err)

ret:

  • 类型:JSON 对象
  • 内部字段:
{
    eventType:'',    //字符串类型;交互事件类型;取值范围:
                     //error:发生错误
                     //complete:发送完成
                     //sending:发送中 (Android 不支持)
    partialLength:   //数字类型;发送进度;仅当 sending 时有值
}

err:

  • 类型:JSON 对象
  • 内部字段:
{
   msg:''          //字符串类型;错误信息
}

示例代码

var ArgFace = api.require('AsyncSocket');
ArgFace.sendToServer({
    data:'123456',
    IP:'172.20.10.1',
    port:3445
},function(ret,err){
    api.alert({msg:JSON.stringify(ret)});
});

可用性

Android 系统,iOS 系统

可提供的 1.0.0 及更高版本