# wsock.tcp.asyncClient 库模块帮助文档

## tcpaclientObject 成员列表 <a id="tcpaclientObject" href="#tcpaclientObject">&#x23;</a>

### tcpaclientObject._form <a id="tcpaclientObject._form" href="#tcpaclientObject._form">&#x23;</a>
用于处理套接字消息的窗口对象  

[返回对象:winform](https://www.aardio.com/zh-cn/docs/library-reference/win/ui/_.html#winform)

### tcpaclientObject.asyncSelect(event) <a id="tcpaclientObject.asyncSelect" href="#tcpaclientObject.asyncSelect">&#x23;</a>
检测到由event参数指明的网络事件后,  
参数@1使用_FD_前缀的常量指定,可使用位或操作符指定多个选项  
事件到达会触发相应的事件(参考on前缀的事件函数),  

失败返回null,以及错误信息,  
成功返回true,以及上次调用此函数指定的event参数

### tcpaclientObject.bind <a id="tcpaclientObject.bind" href="#tcpaclientObject.bind">&#x23;</a>
绑定 IP 端口。

### tcpaclientObject.bind(IP,端口) <a id="tcpaclientObject.bind" href="#tcpaclientObject.bind">&#x23;</a>
绑定 IP 端口。  
如果不指定 IP 则默认绑定 0.0.0.0。  

成功返回 true，  
失败返回 null,错误信息,错误代码。  

同一套接字重复绑定会返回 10022（_WSAEINVAL） 错误。  
重新绑定应当重新创建套接字。  
这就好比一张车票只能上一次车。  
不能在已经上车以后再要求车站修改车票上的上车地。

### tcpaclientObject.bufferSize <a id="tcpaclientObject.bufferSize" href="#tcpaclientObject.bufferSize">&#x23;</a>
读写缓冲区大小，默认为64KB  
缓冲区如果设置的太小，会导致过于频繁的调用读写函数

### tcpaclientObject.close() <a id="tcpaclientObject.close" href="#tcpaclientObject.close">&#x23;</a>
关闭TCP客户端。  
如果未显式调用此函数，在对象析构时将会自动调用。  

已断开连接的套接字不能再使用，需要重连接请重新创建套接字。  
就好比用过的车票不能重复用，什么地方都有规则和限制。

### tcpaclientObject.connect <a id="tcpaclientObject.connect" href="#tcpaclientObject.connect">&#x23;</a>
创建连接。  

已关闭的套接字不能再使用，需要重连接请重新创建套接字。  
就好比用过的车票不能重复用，什么地方都有规则和限制。

### tcpaclientObject.connect(IP或域名,端口号) <a id="tcpaclientObject.connect" href="#tcpaclientObject.connect">&#x23;</a>
创建连接。  
也可以在参数 @1 中用一个字符串同时指定 IP 和端口号,IP 与端口号使用冒号分隔。  
异步套接字始终返回 null ，在 onOpen ,onError 回调事件中判断是否连接成功。

### tcpaclientObject.eachRead <a id="tcpaclientObject.eachRead" href="#tcpaclientObject.eachRead">&#x23;</a>

```aardio
for(str,readSize,remainSize in tcpaclientObject.eachRead() ){   
	/*可选指在eachRead参数中指定最大长度,  
读取长度不可指定负数  

迭代变量:  
str是本迭代次读取的字符串,readSize是读取的长度,	  
remainSize是剩余还没有读取的字节,	  
如果限定了最大长度,remainSize为0时才表示读完所有数据,	  
此函数不支持unRead送回的数据,  
异步客户端只能在onRead事件中使用  

如果套接字没有断开,并且出没有遇到错误,  
但是还没有数据到达,此函数会等待数据  
但不会阻塞消息循环*/  
}
```

### tcpaclientObject.eachReadBuffer <a id="tcpaclientObject.eachReadBuffer" href="#tcpaclientObject.eachReadBuffer">&#x23;</a>

```aardio
for(readSize,remainSize in tcpaclientObject.eachReadBuffer() ){   
	/*可选指在eachReadBuffer参数中指定最大长度,  
读取长度不可指定负数  

迭代变量:  
readSize是本次迭代读取的长度,buffer的实际长度可能大于readSize,	  
remainSize是剩余还没有读取的字节,	  
如果限定了最大长度,remainSize为0时才表示读完所有数据,	  
此函数不支持unRead送回的数据,  
异步客户端只能在onRead事件中使用  

如果套接字没有断开,并且出没有遇到错误,  
但是还没有数据到达,此函数会等待数据  
但不会阻塞消息循环*/  
}
```

### tcpaclientObject.flush() <a id="tcpaclientObject.flush" href="#tcpaclientObject.flush">&#x23;</a>
兼容aardio标准流接口

### tcpaclientObject.getLocalIp() <a id="tcpaclientObject.getLocalIp" href="#tcpaclientObject.getLocalIp">&#x23;</a>
返回连接的本地IP,端口号

### tcpaclientObject.getRemoteIp() <a id="tcpaclientObject.getRemoteIp" href="#tcpaclientObject.getRemoteIp">&#x23;</a>
返回连接的远程IP,端口号

### tcpaclientObject.getSocketError() <a id="tcpaclientObject.getSocketError" href="#tcpaclientObject.getSocketError">&#x23;</a>
获取并同时清除套接字错误代码

### tcpaclientObject.getopt(_SO) <a id="tcpaclientObject.getopt" href="#tcpaclientObject.getopt">&#x23;</a>
获取选项  
参数@1使用_SO_前缀的常量指定选项,参数@2使用结构体指定值  
如果不指定参数@2,则获取一个32位整型数值,  
可选用参数@3指定设置层次，默认为SOL_SOCKET  
成功返回读取的结构体

### tcpaclientObject.hSocket <a id="tcpaclientObject.hSocket" href="#tcpaclientObject.hSocket">&#x23;</a>
套接字句柄  
关闭对象后为空值  
此值应由对象自动维护，调用者不应修改此属性

### tcpaclientObject.isClosed() <a id="tcpaclientObject.isClosed" href="#tcpaclientObject.isClosed">&#x23;</a>
套接字是否已关闭

### tcpaclientObject.isConnected() <a id="tcpaclientObject.isConnected" href="#tcpaclientObject.isConnected">&#x23;</a>
套接字是否已连接

### tcpaclientObject.lastSelectEvent <a id="tcpaclientObject.lastSelectEvent" href="#tcpaclientObject.lastSelectEvent">&#x23;</a>
最后一次调用asyncSelect应用的事件  
不可手动修改此属性，应由对象自动维护

### tcpaclientObject.lastSelectHwnd <a id="tcpaclientObject.lastSelectHwnd" href="#tcpaclientObject.lastSelectHwnd">&#x23;</a>
最后一次调用asyncSelect应用的窗口句柄  
不可手动修改此属性，应由对象自动维护

### tcpaclientObject.lastSelectMessageId <a id="tcpaclientObject.lastSelectMessageId" href="#tcpaclientObject.lastSelectMessageId">&#x23;</a>
最后一次调用asyncSelect应用的消息ID  
不可手动修改此属性，应由对象自动维护

### tcpaclientObject.peek(长度) <a id="tcpaclientObject.peek" href="#tcpaclientObject.peek">&#x23;</a>
读取但并不移除缓冲区的数据,返回字符串  
不指定参数则使用bufferSize指定的大小分配buffer并尝试读取

### tcpaclientObject.read(读取长度) <a id="tcpaclientObject.read" href="#tcpaclientObject.read">&#x23;</a>
读取数据  
只能在onRead事件中使用  
参数可以指定长度,也可以使用接收数据的结构体作为参数  
此函数会循环读取数据，  
如果当前没有数据此函数会立即返回不会阻塞  
如果读取长度指定为负数,此函数会等待数据到达直到读取全部数据  
等待过程中不会阻塞消息循环  
不指定读取长度时表示读取一行,  
使用CRLF回车换行符分行  

此函数如果读取部分不完整数据会调用 unRead 函数退回缓冲区  
读取不到任何数据会调用shutdown函数关闭连接

### tcpaclientObject.readAll() <a id="tcpaclientObject.readAll" href="#tcpaclientObject.readAll">&#x23;</a>
读取全部数据  
只能在onRead事件中使用

### tcpaclientObject.readAlloc <a id="tcpaclientObject.readAlloc" href="#tcpaclientObject.readAlloc">&#x23;</a>
循环读取数据到动态指针内,  
对于异步套接字，只能在onRead函数内使用此函数,  
动态指针的使用风险较大,如果不是非常熟悉其规则,  
建议不要使用此函数  

对象所有read前缀的成员函数底层基本都是调用这个函数  
此函数读取的数据支持调用unRead或unReadAlloc,  
撤消并退回到读缓冲区

### tcpaclientObject.readAlloc() <a id="tcpaclientObject.readAlloc" href="#tcpaclientObject.readAlloc">&#x23;</a>
循环读取数据，直到读取结束,

### tcpaclientObject.readAlloc(动态指针) <a id="tcpaclientObject.readAlloc" href="#tcpaclientObject.readAlloc">&#x23;</a>
循环读取数据并存入参数指定的动态指针,  
返回新的指针地址和内存长度,  
此函数可能更新指针地址或分配的内存大小，  
必须使用返回的新指针覆盖原来保存该动态指针的变量值

### tcpaclientObject.readAlloc(读取长度) <a id="tcpaclientObject.readAlloc" href="#tcpaclientObject.readAlloc">&#x23;</a>
循环读取数据，直到达到参数中限定的最大长度  
无数据返回null，  

如果读取到数据则返回2个值：动态指针,内存长度  
调用者必须负责调用 raw.realloc(0,动态指针)  
释放返回值1返回的指针  

此函数直接操作内存，效率更好  
但一定要记住释放返回的内存指针

### tcpaclientObject.readBuffer(buffer,读取长度) <a id="tcpaclientObject.readBuffer" href="#tcpaclientObject.readBuffer">&#x23;</a>
读取数据,返回 buffer 对象,  
省略所有参数则读取所有数据，  
参数@1可选指定一个使用 buffer 对象，  
省略读取长度时取缓冲区长度，  

如果参数@1指定了缓冲区,成功返回读取长度,  
否则成功返回缓冲区，  
失败返回null  

如果指定了长度,没有到完整的数据时,  
此函数会将数据退回缓冲区,并返回null  
如果读取出错,或没有读取到数据,此函数会自动调用shutdown关闭连接

### tcpaclientObject.readDelayInterval <a id="tcpaclientObject.readDelayInterval" href="#tcpaclientObject.readDelayInterval">&#x23;</a>
数据尚未到达时的等待时间  
此属性仅适用于界面线程异步套接字  
仅在所有read前缀的读数据函数中，读取长度为负值是有效,  
each前缀的迭代器函数也使用此属性指定的等待时间

### tcpaclientObject.readOobByte() <a id="tcpaclientObject.readOobByte" href="#tcpaclientObject.readOobByte">&#x23;</a>
读取一个字节的紧急数据,返回字节码

### tcpaclientObject.readTo <a id="tcpaclientObject.readTo" href="#tcpaclientObject.readTo">&#x23;</a>
读取直到以指定的字符串结束  
只能在onRead事件中使用  

此函数如果读取部分不完整数据会调用 unRead() 退回缓冲区  
读取不到任何数据会调用shutdown函数关闭连接

### tcpaclientObject.readTo('结束串') <a id="tcpaclientObject.readTo" href="#tcpaclientObject.readTo">&#x23;</a>
读取直到以指定的字符串结束,返回值不包含结束串,  
该函数每次仅读取一个字节,效率较低  
只能在onRead事件中使用

### tcpaclientObject.readTo('结束串',true) <a id="tcpaclientObject.readTo" href="#tcpaclientObject.readTo">&#x23;</a>
读取直到以指定的字符串结束,返回值不包含结束串,  
如果没有读取到数据，则循环等待，等待时继续处理界面消息  
此用法仅适用于界面线程异步套接字  
该函数每次仅读取一个字节,效率较低

### tcpaclientObject.readyState <a id="tcpaclientObject.readyState" href="#tcpaclientObject.readyState">&#x23;</a>
套接字连接状态,  
0为等待连接,1为已连接,2为正在关闭,3为已关闭

### tcpaclientObject.recv(最大接收长度) <a id="tcpaclientObject.recv" href="#tcpaclientObject.recv">&#x23;</a>
单次接收数据包  
如果参数不指定长度，则使用bufferSize指定的长度  
成功返回字符串,  
失败返回null,错误代码  

recv,recvBuffer应在onReceive事件中使用，  
在onReceive里不能多次调用recv,recvBuffer。  
recv,recvBuffer不保证每次一定会读完数据，所以在onClose事件里要继续读到没有任何数据。  

在 onRead事件中调用read前缀的系列函数可以循环读取所有接收的数据，  
这样就可以避免onClose以后还数据没有收完的问题

### tcpaclientObject.recvBuffer(缓冲区,读取长度) <a id="tcpaclientObject.recvBuffer" href="#tcpaclientObject.recvBuffer">&#x23;</a>
单次接收数据包  
参数@1指定 buffer 对象,  
参数@2可省略,默认为缓冲区长度,  
成功返回接收的长度,  
失败返回null,错误代码  

recv,recvBuffer应在onReceive事件中使用，  
在onReceive里不能多次调用recv,recvBuffer。  
recv,recvBuffer不保证每次一定会读完数据，所以在onClose事件里要继续读到没有任何数据。  

在 onRead事件中调用read前缀的系列函数可以循环读取所有接收的数据，  
这样就可以避免onClose以后还数据没有收完的问题

### tcpaclientObject.send(数据,长度) <a id="tcpaclientObject.send" href="#tcpaclientObject.send">&#x23;</a>
单次发送数据包

### tcpaclientObject.setTimeouts(发送超时,接收超时) <a id="tcpaclientObject.setTimeouts" href="#tcpaclientObject.setTimeouts">&#x23;</a>
设置超时,以亳秒为单位(1秒为1000毫秒)

### tcpaclientObject.setopt(_SO) <a id="tcpaclientObject.setopt" href="#tcpaclientObject.setopt">&#x23;</a>
设置选项  
参数@1使用_SO_前缀的常量指定选项,参数@2使用结构体或数值指定值  
可选用参数@3指定设置层次，默认为SOL_SOCKET  
成功返回true

### tcpaclientObject.shutdown() <a id="tcpaclientObject.shutdown" href="#tcpaclientObject.shutdown">&#x23;</a>
断开连接。  
参数中指定 0 为仅停止收数据，指定 1 为停止发送数据。  
默认值为 2 表示停止收发数据。  
此函数并不销毁套接字句柄，也不会关闭事件监听器。  

已断开连接的套接字不能再使用，需要重连接请重新创建套接字。  
就好比用过的车票不能重复用，什么地方都有规则和限制。

### tcpaclientObject.unRead() <a id="tcpaclientObject.unRead" href="#tcpaclientObject.unRead">&#x23;</a>
把read,readTo,readBuffer等函数读出的数据退回缓存，  
注意退回数据的顺序是“后出先进”，  
最后读出的应当最先退回

### tcpaclientObject.unReadAlloc() <a id="tcpaclientObject.unReadAlloc" href="#tcpaclientObject.unReadAlloc">&#x23;</a>
把readAlloc读取的动态指针退回缓存,  

注意退回数据的顺序是“后出先进”，  
最后读出的应当最先退回

### tcpaclientObject.write(...) <a id="tcpaclientObject.write" href="#tcpaclientObject.write">&#x23;</a>
发送数据。  
支持一个或多个参数，参数支持字符串、buffer (buffer)、数值、结构体。  
此函数一定会写完所有的输入数据，除非套接字被关闭。  
即使是异步套接字，也会自动缓存未发送完成的数据，并继续异步发送直到成功。  
此函数执行成功返回 true  

写入结构体请务必注意：  
1. 网络协议使用的结构体都是紧凑结构体（不使用主机构构体对齐规则以避免不同主机差异）,  
如果结构体对齐与不对齐的大小不一样，请在结构体中添加 _struct_aligned=1 禁用对齐。  
2. 网络协议使用的数值字节序都是大端序，而 aardio 使用默认的小端序（主机字节序）。  
可使用 raw.swap 函数转换字节序。

### tcpaclientObject.writeBuffer(buffer,长度) <a id="tcpaclientObject.writeBuffer" href="#tcpaclientObject.writeBuffer">&#x23;</a>
发送数据,  
参数@1应使用 buffer 对象,  
可选使用参数2指定长度  
成功返回true

## tcpaclientObject 事件列表 <a id="tcpaclientObjectEvent" href="#tcpaclientObjectEvent">&#x23;</a>

### tcpaclientObject.onClose <a id="tcpaclientObject.onClose" href="#tcpaclientObject.onClose">&#x23;</a>

```aardio
tcpaclientObject.onClose = function(err){
	/*已断开连接,  
如果缓冲区中仍然有数据,  
这个事件可能在其他事件前面触发*/	
}
```

### tcpaclientObject.onConnect <a id="tcpaclientObject.onConnect" href="#tcpaclientObject.onConnect">&#x23;</a>

```aardio
tcpaclientObject.onConnect = function(err){
	/*连接操作已完成,  
连接成功时err为0，且readyState为1,  
在这里可以开始发送数据*/	
}
```

### tcpaclientObject.onOutOfBandData <a id="tcpaclientObject.onOutOfBandData" href="#tcpaclientObject.onOutOfBandData">&#x23;</a>

```aardio
tcpaclientObject.onOutOfBandData = function(err){
	/*收到紧急数据,  
即send函数最后一个flag参数设为_MSG_OOB时发送的1字节带外数据*/		
}
```

### tcpaclientObject.onRead <a id="tcpaclientObject.onRead" href="#tcpaclientObject.onRead">&#x23;</a>

```aardio
tcpaclientObject.onRead = function(err){
	/*收到数据,  
可阻塞读取数据,  
定义了此事件就不应同时定义onReceive事件*/	
}
```

### tcpaclientObject.onReceive <a id="tcpaclientObject.onReceive" href="#tcpaclientObject.onReceive">&#x23;</a>

```aardio
tcpaclientObject.onReceive = function(err){
	/*收到数据,  
仅读取已到达的数据,  
定义了此事件就不应同时定义onRead事件*/	
}
```

### tcpaclientObject.onSend <a id="tcpaclientObject.onSend" href="#tcpaclientObject.onSend">&#x23;</a>

```aardio
tcpaclientObject.onSend = function(err){
	/*发送数据*/
}
```

## wsock.tcp 成员列表 <a id="wsock.tcp" href="#wsock.tcp">&#x23;</a>

### wsock.tcp.asyncClient <a id="wsock.tcp.asyncClient" href="#wsock.tcp.asyncClient">&#x23;</a>
TCP异步客户端  
创建监听器

### wsock.tcp.asyncClient() <a id="wsock.tcp.asyncClient" href="#wsock.tcp.asyncClient">&#x23;</a>
创建TCP异步客户端

[返回对象:tcpaclientObject](#tcpaclientObject)

### wsock.tcp.asyncClient(套接字句柄) <a id="wsock.tcp.asyncClient" href="#wsock.tcp.asyncClient">&#x23;</a>
绑定异步套接字返回客户端对象  
不创建事件监听器
