您的位置:程序门 -> vb -> 网络编程



求救:winsock传送二进制文件丢包的问题


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


求救:winsock传送二进制文件丢包的问题[已结贴,结贴人:jzmark]
发表于:2007-03-07 18:43:32 楼主
做一个局域网内的下载功能,现在会出现客户端收到的文件比源文件小的情况。哪位能帮我看看,谢谢。
服务器端发送程序:
sub   sendfiletoclient(xfilename   as   string,   ipaddy   as   string,   whichwinsock   as   winsock)
        on   error   goto   errorhandler
        dim   buffer   as   string
        dim   buffersize   as   integer
        dim   filelength   as   long,   superbuffer   as   long,   timeout   as   long
        dim   i   as   integer
        dim   j   as   integer
        buffersize   =   2048                        
        do   while   whichwinsock.state   <>   7:   doevents
                if   whichwinsock.state   =   sckerror   then
                        writeerrlog   "winsock   error: "   &   vbcrlf   &   err.description:   exit   sub
                end   if
        loop
        startsending   =   false
        whichwinsock.senddata   "filesize= "   &   filelen(xfilename)
        do   while   startsending   <>   true
                doevents
        loop
        i   =   freefile   'find   free   file
        open   xfilename   for   binary   access   read   as   #i
        filelength   =   lof(i)
        do   while   not   eof(i)
                doevents
                if   filelength   -   loc(i)   <   buffersize   then
                        let   buffersize   =   filelength   -   loc(i)
                        if   buffersize   =   0   then   goto   done
                end   if
                'buffer   =   space(buffersize)
                redim   abuf(0   to   buffersize   -   1)
                get   #i,   ,   buffer
                whichwinsock.senddata   buffer)
                superbuffer   =   superbuffer   +   len(buffer)
                '等待客户端接受以后再发
                do   while   (timeout   <   10000)
                        doevents
                        timeout   =   timeout   +   1
                        if   timeout   >   10000   then   exit   do
                loop
                'debug.print   j
                timeout   =   0
        loop
done:
        close   #i
        whichwinsock.senddata   "sendend "
        do   while   (timeout   <   10000)
                doevents
                timeout   =   timeout   +   1
                if   timeout   >   10000   then   exit   do
        loop
        startsending   =   false
        writeerrlog   "sent   ' "   &   xfilename   &   " '   ( "   &   superbuffer   &   "   bytes)   to   ip   ' "   &   ipaddy   &   " '   time/date= "   &   format(now,   "yyyy/mm/dd   hh:mm:ss ")
        exit   sub
errorhandler:
        writeerrlog   "sent   ' "   &   xfilename   &   " 'to   ip   ' "   &   ipaddy   &   " '   time/date= "   &   format(now,   "yyyy/mm/dd   hh:mm:ss ")   &   "出现错误: "   &   err.description
end   sub

客户端接收


private   sub   winsock_dataarrival(byval   bytestotal   as   long)
        dim   data   as   string
        dim   receivearr()           as   byte
        if   winsock.state   <>   7   then   exit   sub
        call   winsock.getdata(data,   ,   bytestotal)
        if   left(data,   6)   =   "error: "   then
                blnerror   =   true
                fcomplete   =   true
                exit   sub
        end   if
        if   left(data,   9)   =   "filesize= "   then
                filesize   =   right(data,   len(data)   -   9)
                inr   =   1
                if   filesize   =   0   then
                        close   #filenum
                        fcomplete   =   true
                        exit   sub
                end   if
                call   client.senddata( "begin ")
                exit   sub
        end   if
        if   data   =   "sendend "   then
                close   #filenum
                fcomplete   =   true
                exit   sub
        end   if
       
        if   filenum   >   0   then
                put   #filenum,   ,   data
                'debug.print   inr
                inr   =   inr   +   1
                if   lof(filenum)   =   filesize   then
                        close   #filenum
                        fcomplete   =   true
                        exit   sub
                end   if
        end   if
end   sub
发表于:2007-03-07 20:22:321楼 得分:100
唉,这个代码,几乎没注释……

只说两点吧:
1.   如果发送的数据大于8k,会激发多次dataarrival事件,你的服务器端代码必须将接收的数据拼起来
2.   客户端分两次发送的数据,服务器端可能会并为一次接收,也就是说只激发一次dataarrival事件

代码根本不用这么烦的,给段参考吧:

发送方(我这里是客户端)
'先发送文件名和大小,dlg为通用对话框的名称,用到一些控件,你看前缀就知道是什么控件了
private   sub   cmdsend_click()
        dlg.filename   =   " "
        dlg.filter   =   "所有文件 ¦*.* "
        dlg.showopen
        if   dlg.filename   <>   " "   then
                wsclient.senddata   "$start* "   &   dlg.filetitle   &   "* "   &   filelen(dlg.filename)
                lblstate.caption   =   "准备传送文件,等待对方应答... "
        end   if
end   sub

'对方响应后发送实际文件
private   sub   wsclient_dataarrival(byval   bytestotal   as   long)
        dim   s   as   string
        wsclient.getdata   s,   vbstring
        if   s   =   "no "   then
                lblstate.caption   =   "对方拒绝接收 "
        else
                wsclient.senddata   filetobytes(dlg.filename)
                lblstate.caption   =   "正在传送文件... "
        end   if
end   sub

'文件转为字节数组
private   function   filetobytes(filename   as   string)   as   byte()
        dim   byt()   as   byte
        open   filename   for   binary   as   #1
                redim   byt(lof(1)   -   1)
                get   #1,   1,   byt
        close   #1
        filetobytes   =   byt
end   function


接收方,dlg为通用对话框的名称
private   sub   wsserver_dataarrival(byval   bytestotal   as   long)
        dim   byt()   as   byte
        dim   strfileinfo   as   string
        static   issendbytes   as   boolean
        static   info()   as   string
       
        on   error   goto   ext
       
        if   issendbytes   =   false   then
                wsserver.getdata   strfileinfo,   vbstring
                info   =   split(strfileinfo,   "* ")
                if   info(0)   <>   "$start "   then   exit   sub
                if   msgbox( "对方向你发送文件“ "   &   info(1)   &   "”,大小为 "   &   info(2)   &   "字节,是否接收? ",   vbquestion   +   vbyesno)   =   vbno   then
                        wsserver.senddata   "no "
                else
                        dlg.filename   =   info(1)
                        dlg.filter   =   "所有文件 ¦*.* "
                        dlg.showsave
                        wsserver.senddata   "yes "     '向对方发送开始传送文件标志
                        issendbytes   =   true
                end   if
        else
                lblstate.caption   =   "正在接收文件,已接收 "   &   bytestotal   &   "字节 "
                if   bytestotal   > =   info(2)   then     '如果接收到的数据大于等于文件大小,表示接收完毕
                        wsserver.getdata   byt,   vbbyte   +   vbarray
                        bytestofile   byt,   dlg.filename
                        issendbytes   =   false
                        lblstate.caption   =   "文件已接收完毕 "
                end   if
        end   if
        exit   sub
ext:
      wsserver.senddata   "no "     '点击取消,将引发错误,则向对方发送不同意传送文件的标志。此处省略了判断错误号的操作
end   sub

'字节数组转为文件
private   sub   bytestofile(byt()   as   byte,   filename   as   string)
        if   dir(filename)   <>   " "   then   kill   filename
        open   filename   for   binary   as   #1
                put   #1,   1,   byt
        close   #1
end   sub
发表于:2007-03-07 22:41:162楼 得分:0
搞清楚问题了,是因为发送和接受用的是字符串,不是byte数组,谢谢


快速检索

最新资讯
热门点击