|
本帖最后由 itljl 于 2010-1-24 19:29 编辑
论坛上讨论TCP的少,我也来发一个吧。
重点是,用同一个端口,同一个SOCKET连接,既发送文字信息又发送二进制文件信息,也就是一程序是侦听端,一个程序是连接端,但两个程序都要能给对方发送文字信息与二进制文件信息,并都能接收文字信息与二进制文件信息。
最下面附有,用AU3,TCP发送和接收文件的示例。今天讨论的内容是,在同一个SOCKET中如果既发送信息,又发送文件。当然论坛上有朋友做了新的UDF,还有详尽的示例来演示。但是,他们都有一个地方没有处理好。
问题出在,接收文件的循环。
在文件接收循环,在论坛已有的例子中,有两种情况认为文件传送完成
第一种:
局域网通信核心程序(聊天、群发、传文件、维护通道等)元旦修正版
http://www.autoitx.com/forum.php ... p;extra=&page=1
$rData = TCPRecv($rAccept, 1024 * 1024, 1);开始接收文件
If Not @error Then
注意这里,如果没有错误。也就是如果有错误就退出文件接收这个循环,怎样会有错误?那就是对方断开这个socket连接。如果我们即要发送文字信息,又要发送文件的二进制信息。这里就不能断开连接。
(注意,如果对方没发送信息了,socket是正常连接着的,这里的tcprecv是不会出错的,只会返回空字符。)
另外一种
If $ri >= $rDays[3] Then ExitLoop
当接收到的二进制总字节数大于文件的信息时,退出接收文件循环
这也是行不通的,为什么?因为TCPRecv并不是按序列一条一条接收信息。而是从SOCKET中按设定好的大小 1024 * 1024 来接收。
所以,当对方发送文件完成后,并立即发送文件信息时,这个文件信息还是会被写入到文件中。
目前马马虎虎的方法就是发送文件用一个新的SOCKET,发送完成就断开。在 TCPRecv 下面检测出错就退出文件接收循环,并关闭连接,关闭文件。
但这样做的不好就是要新开一个SOCKET,那就必须接收一方要在开始侦听端口,这样将导致发送端与接收端都要同时侦听端口。
一是应用在外网上面,无论正向还是反向连接,路由器上必须开端口印射
二是,不能在同一台机子上开服务端与客户端。(因为同一个端口只能被一个程序侦听。)
谁有更好的办法来判断文件循环发送完成呢?欢迎讨论。
-----------------------------------------
接收
$R_ip = @IPAddress1
$R_File = @ScriptDir & "\R.jpg"
$R_Prot = 65432
$var = _recvFiles($R_ip, $R_File, $R_Prot)
MsgBox(0, "接收端", $var)
Func _recvFiles($R_ip, $R_File, $R_Prot);接收文件
Local $i
TCPStartup(); 开始 TCP 服务
$MainSocket = TCPListen($R_ip, $R_Prot, 100); 创建监听套接字(SOCKET)
If $MainSocket = -1 Then Return "1,创建监听套接字失败"
; 查看客户端连接
While 1
TrayTip("", "等待连接", 3)
$ConnectedSocket = TCPAccept($MainSocket)
If $ConnectedSocket >= 0 Then
$file = FileOpen($R_File, 2 + 8 + 16);打开文件准备接收
If $file = -1 Then
Return "2,无法打开文件"
Exit
EndIf
While 1;开始接收文件
$i += 1
TrayTip($i, "开始接收文件", 3)
$sBuff = TCPRecv($ConnectedSocket, 1024 * 1000, 1)
If @error Then
FileClose($R_File)
Return "3,文件接收完成"
EndIf
;写文件
FileWrite($R_File, $sBuff)
WEnd
EndIf
WEnd
Return 1
TCPCloseSocket($ConnectedSocket);关闭套接字,停止TCP服务
TCPShutdown()
EndFunc ;==>_recvFiles
发送
$S_ip = InputBox("please input ipaddress", "please input ipaddress",@IPAddress1)
$S_File = @ScriptDir & "\S.jpg"
$S_Prot = 65432
$var = _SendFile($S_ip, $S_File, $S_Prot)
MsgBox(0, "", $var)
Func _SendFile($S_ip, $S_File, $S_Prot)
Local $i
;开始tcp服务
TCPStartup()
;创建一个套接字(socket)连接到已经存在的服务器
TrayTip("", "1 连接到服务器", 3)
$socket = TCPConnect($S_ip, $S_Prot)
If $socket = -1 Then
Return "连接到服务器出错: " & @error
Exit
EndIf
$File = FileOpen($S_File, 16)
if $File = -1 Then return "2 文件打开失败"
;打开读取文件
While 1
$i += 1
TrayTip($i, "3 发送文件", 3)
$fdata = FileRead($File,1024 * 1000)
If @error = -1 Then ExitLoop
TCPSend($socket, $fdata)
WEnd
TCPCloseSocket($socket)
TCPShutdown()
Return 1
EndFunc ;==>_SendFile |
|