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