转贴关于TCP通讯的文章--Thinking在Au3中TCP编程的三年经验
转自ThinKing(bbs.wglm.net)以下是Thinking三年在au3中TCP编程的经验。理论为主,大家如果有不懂的地方,可以继续跟贴提问,我上线后会及时解答。
附件中为最基本的AU3 TCP通讯例子。
本文将试图通过AU3来了解一下TCP C/S编程的方式和原理。本文只适合有编程经验(至少一种编程语言)的同志阅读。
首先,我们以一个au3官方的基本例子开始。试图解决了解和解决以下问题。也是我曾经迷茫和难以解决的问题。
基础知识
一 在AU3中TCP通讯的基本原理。(其它编程中大同小异)
二 一次发送的数据是多大?
三 中文乱码如何解决?
四 没有多线程要同时做多件事如何解决?
五 WAN和LAN在TCP编程中的有何区别?
六 如何防止丢失信息?
七 因为AU3是单线程,那假设客户端发送信息,服务端正在忙于其它时间未收到怎么办?
八 是不是每时每刻都要关注TCP信息?
九 一个服务端,多个客户端同时如何通讯?
十 其它注意。
零 基本知识
1什么是端口。
端口是计算机网络通讯的虚拟的一个门,就好比你要进入网吧,得有个门一样。
端口的范围1-65535共 65536个。其中1-1024一般被系统规定为固定端口,如80是TCP服务。所以我们编程时最好选用 1025-65535之间。dbnt我用的是 21984。
2什么socket
你可以想成是一个通道。有了门,如果没有连接这个门的通道,还是不能通讯的。就好比你的宿舍有门,网吧也有门,但没有通道,你仍然不能从宿舍走到网吧。
一 在AU3中TCP通讯的基本原理。(其它编程中大同小异)
服务端客户端本身无严格定义。随便你叫哪端为什么端。但通常我们叫最常在线那个叫服务端。
我们首先定义一下,服务端:那个常在线,监听接收数据的端。客户端,那个随时可上线下线,连接发送消息的端。
服务端
1,TCPStartup()
首先我们要启用TCP服务
2,$MainSocket = TCPListen($szIPADDRESS, $nPORT)
我们要在本地监听一个端口,这个端口不能是已经被使用的。如果执行成功,那么 $MainSocket 就是一个主要的,对应我们刚监听的端口的主socket,我们可以通过这个 $MainSocket 标识来接受来自客户端的连接
一个程序可以有多个由 TCPListen 获得的 $MainSocket 分别对应不同的端口。
3
Do
$ConnectedSocket = TCPAccept($MainSocket)
Until $ConnectedSocket <> -1
的意思则是,服务端程序一直等待,直到 TCPAccept 收到一个客户端的连接,再结束这个循环。成功后 $ConnectedSocket 就是一个服务端到客户机的专用连接。利用对 $ConnectedSocket 的读和写,就可以实现服务器与客户机的通信。
4 $recv = TCPRecv($ConnectedSocket, 2048)
不停的利用 TCPRecv 接收 $ConnectedSocket的数据,当为空时,表示没有数据收到,当出错时,表示客户机断开了。有数据时,就可以显示或者作其它的处理。
以上是一个服务端的完整过程。
5,而利用tcpsend则可以向客户端发送消息。服务是即可以接收消息,也可以发送消息。
客户端
1 TCPStartup()
略
2 $ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)
表示向一个服务器IP和端口发起连接,如果成功,就会产生一个 socket 标识, $ConnectedSocket,通过对该标识的读和写就可以实现数据的发送和接收。
3,TCPSend($ConnectedSocket, $szData)
即时通过 $ConnectedSocket socket标识向之前建立的连接发送消息。
4,而利用 tcprecv则可以接收服务端发送来的消息。客户端是即可以接收消息,也可以发送消息。
综上就是完整的过程,因TCP是全双工通信,所以,即可发,也可以收。这也正是服务器和客户端定义不明朗的原因。
二 一次发送的数据是多大?
曾看文章说TCP发送文件时,如果太大,则要重新封包。其实没有必要。无论你怎么重新封包数据。而TCP在发送时一般都会是64KB,他会根据网络的定义重新定义大小,一般都是64KB,
所以,就算是你 TCPRecv ( 主套接字, 最大返回量[, 标志]) 的最大返回量设得很大,如果是及时接收的话,每次不会超过64KB太多。不及时接收的话,可能会堆积较多数据。
三中文乱码如何解决?
在tcpsend发送数据之前,先将中文字符串转成二进制,TCPSend($sockt, StringToBinary($Rorder, 4)) ,接收时再转回来
binarytostring($recv,4) 即可还原。
四没有多线程要同时做多件事如何解决?
之前我考虑过一个问题,那就是,当一个服务端和2个客户端同时通信时,AU3由不会多线程,如何同时响应两个客户机发来的消息呢?如果没有及时接收,会不会收一台的消息,丢失另一台的消息呢?
在了解了TCP通信原理后才发现,我根本不需要考虑这个问题。因为一旦我们 TCPAccept 接受连接成功 或者 tcpconnect 连接成功后。系统就接手了通讯。所以我们并不需要,同时去接收两台客户机的消息。
而只要慢条斯理对不同的连接$socket 进行循环接收消息就行了。
如
while 1
$var1 = TCPRecv($ConnectedSocket1, 2048)
if $var1 <> “” Then msgbox(0,0,$var1)
$var2 = TCPRecv($ConnectedSocket2, 2048)
if $var2 <> “” Then msgbox(0,0,$var2)
sleep(1000)
wend ;(当然,实际使用中,我们应该是以 for 循环数组的方式,动态更新多个SOCKET)
我们甚至可以sleep1秒钟的原因是,系统会即时帮我们接收客户端发送来的消息。所以,只要我们忙完后,从soctet去接收消息来处理就可以了。不用急。
五 WAN和LAN在TCP编程中的有何区别?
注意1,
最需要注意的就是,因为在WAN时,很多时候要经过路由器。经过路由器需要端口映射,所以,我们得把程序尽可能得设计得只需要一个socket,
如果需要客户端和服务端分别进程一次tcpconnect,那就是两个socket,就得在两个路由器上映射。非常不便。
注意2,
WAN比LAN慢得多,得尽可能少的减少数据的发送和接收量。
六如何防止丢失信息?
TCP是可靠的面对向对像的连接,发送的数据是不会丢失的.在AU3中遇到的丢失现像就是当发送的数据超过TCP封装的包时,而接收端只接收了一次.就会出现丢失.
这种情况的解决办法是,在发送大于64KB的数据时,字符串加一个头和尾
如: {ts}…很多数据…{te} 接收端在收到 {te} 后才将收到的信息进行处理,否则一直循环等待.
七因为AU3是单线程,那假设客户端发送信息,服务端正在忙于其它时间未收到怎么办?
参考第四点
八是不是每时每刻都要关注TCP信息?
参考第四点
九一个服务端,多个客户端同时如何通讯?
参考第四点,同时要注意的时.
当多个客户端,同时发送多个信息时,服务端在AU3没有及时用tcprecv接收的情况下,可能造成信息连在一起.
如:本身是要发送的: “客户机1|关闭窗口|”
但如果没有服务端没有及时接收处理.那就有可能在某次收到的是: “客户机1|关闭窗口|客户机2|关闭进程|”
所以,对于接收到的数据,不管是有没有及时处理,都得用 StringSplit 拆分一下数据并显示.
这样就不会造成信息粘连在一起的情况
十其它注意
1,当一个客户机下线后,客户端应该及时使用 TCPCloseSocket 来释放资源.在一对一的通信中,可能不会有什么问题,当一个服务端有多个客户端时,如果不及时关闭,就会发生你维护的在线列表错乱的情况.
2,对于不用、多余的socket应及时 TCPCloseSocket
3, 发送文件时,为什么发送端发送完文件后,接收端还一直在接收.
因为发送端实际是发送到socket缓冲中.而接收端才是一直在接收.直到结束.
所以,发送一个大文件,每次发10M,其实都是发送到系统的tcp缓冲中,如果你看到完成,马上关闭服务端,接收端就会出错。
所以,发送文件,发送多个文件。应该每接收完一个文件,对发送端发送一个反馈信息,如字符串:{FileRecvEnd}
以AU3为例讲TCP通讯原理(点击下载)
http://115.com/file/dn3c7c61# 坐个板凳哈。。发个例子效果更好哦 谢谢, 接触AU3时间不算短了, 在这方面的知识还从未系统学习过! 哇 这个一定要学 经验总是最宝贵的东西 嗯。说明挺详细。了解了。。谢谢 谢谢楼主分享 太感谢了,早想学习这个了。 非常好~~~~ tcp通讯没有试过,但是用udp通讯做过和几十台电脑通讯的服务端和客户端程序 肯定会用得上,收藏是必须滴 正要这样的,谢谢楼主! 正在学习!谢谢分享了... 回复 1# kk_lee69
虽然年以40,有心无力,但也要支持一下! 作者讲的很仔细很专业,转帖的很无私 好东西 115下载不了了
页:
[1]
2