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



winsock如何接收图片?


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


winsock如何接收图片?[已结贴,结贴人:killl]
发表于:2007-01-07 17:33:14 楼主
奇怪。受到下面数据后,如何继续接受图片呢?

现在只能接收到http信息头,无法接受文件内容?而且bytestotal   的长度是头信息的长度,而不是文件长度。请问如何继续接收数据内容呢/?

http/1.0   200   ok
content-length:   6813
content-type:   image/gif
last-modified:   mon,   04   dec   2006   10:34:41   gmt
accept-ranges:   bytes
etag:   "32cc86ce8f17c71:2bad "
server:   microsoft-iis/6.0
x-powered-by:   asp.net
date:   sun,   07   jan   2007   09:23:53   gmt
age:   100
x-cache:   hit   from   longrujun.name
via:   1.0   longrujun.name:80   (squid/2.6.stable5-20061211)
connection:   close

------------------------------------
接受代码:

private   sub   sk_dataarrival(index   as   integer,   byval   bytestotal   as   long)   '收到数据触

        dim   str   as   string,   i   as   integer,   j   as   integer
        dim   url   as   string,   tmp   as   string
        redim   bybuff(1   to   bytestotal)   as   byte
        sk(0).getdata   bybuff,   vbarray   +   vbbyte
        open   "img.gif "   for   binary   as   #1
        put   #1,   ,   bybuff
        close   #1
end   sub
发表于:2007-01-08 18:25:201楼 得分:0
代码:

private   sub   command1_click()
                httpheader   =   "get   /images/smilies/wizenflower.gif   http/1.1 "   &   vbcrlf   &   _
                                          "content-type:   text/html "   &   vbcrlf   &   _
                                          "host:   www.vbgood.com "   &   vbcrlf   &   _
                                          "accept:   text/html,   */* "   &   vbcrlf   &   _
                                          "user-agent:   mozilla/4.0   (compatible;   msie   6.0;   windows   nt   5.2;   maxthon;   .net   clr   1.1.4322;   .net   clr   2.0.50727) "   &   vbcrlf   &     vbcrlf  

                  socks.connect   "www.vbgood.com ",   "80 "
end   sub

private   sub   socks_connect()
        socks.senddata   httpheader
end   sub
发表于:2007-01-08 20:25:012楼 得分:80
代码:
private   sub   command3_click()
httpheader   =   "get   /images/smilies/wizenflower.gif   http/1.1 "   &   vbcrlf   &   _
                                          "content-type:   text/html "   &   vbcrlf   &   _
                                          "host:   www.vbgood.com "   &   vbcrlf   &   _
                                          "accept:   *.*,   */* "   &   vbcrlf   &   _
                                          "user-agent:   conquest "   &   vbcrlf   &   vbcrlf

socks.connect   "www.vbgood.com ",   "80 "
end   sub

private   sub   socks_connect()
socks.senddata   httpheader
end   sub

private   sub   socks_dataarrival(byval   bytestotal   as   long)
dim   da   as   string
dim   dabytes()   as   byte
redim   dabytes(bytestotal   -   1)
          socks.getdata   da,   vbstring       '为了简化,采用的是vbstring,请自行改为以下
          'socks.getdata   dabytes,   vbbyte
          debug.print   da
end   sub

显示结果:
http/1.1   200   ok
date:   mon,   08   jan   2007   12:22:02   gmt
server:   apache
last-modified:   wed,   13   dec   2006   13:17:41   gmt
etag:   "16a39-13b9-39328740 "
accept-ranges:   bytes
content-length:   5049
content-type:   image/gif


gif87a                f   33f檉衊       fff??`p   ?烫櫎畃€皜虁€犂犩怭癙p€?o          佬腊p   @€@`€   p€   33   @@   p噜郟怭噜惏愋嘈€行?     嗬?€   欣鄍     pp悹`   p   挐t`   p跋胺緧i&0€0衟   @pp   f   览犩嘈€怈`€袪犚赘pp?p嘈邪f3蘤   喟€?   p   鄍   袗?s   p       烫??3嘈癅@   ppp?   邪?   0p?蘤f?   €€?0p   3?繞@郹   ?p燻   €   燖酄`貈 "泰炖戉€p   迴b?0`怈p爌   ??   甙癙€   3       惏€縛`?   牥€郟p佬?`   鄍   袄牥邪p怭?   z~!`嗬爌怈     €0€     p@酄€0@   櫃繮   p?鄝0犂惏缾牥pp€0j牋嚙i繞   酄p0   郹衟喟?p   @   聐`€0p   纏纏p€?軏4爯€衻€袗€?p0p0`@@€   p   ?   啗qw慒f_   檉pp郟€@`p@3f   ?   啞]郂@悾_e歎蠵   p??@0?   @€?   蠤   郂   0€?   0?   綤€??   o??   /?p@?   蠵   蠤蠵衊`@@   行?   癅   繮p; '繞繮@   p€纏p纏`镅肞     嗬班0   鄍0喟?€`   ?   i?v??蠵0怈郟   郹`諉q?蹛r蠵pp`蠤0荬愋00! netscape2.0       !?      ,                      h盃羶*\劝∶?x8l€? "騺? 4i)ⅴ8ad   h0!@k,?缆cnúp盇??霶`?瓒进`   ~ 谩倻 <ht豴       h爡&qz笵d   ??爡醽w?mhyqbe?h荬r冥$ccj0??n心 '?x?癧吤7  
掖?晩%8p   `坆廙84駦棑v霵p
(略)
发表于:2007-01-09 07:35:203楼 得分:20
将文件按1024个字节进行分割,然后再分别依序传输。
发表于:2007-01-09 17:41:064楼 得分:0
谢谢楼上2位,但是我是接受文件啊?

如果小文件,可以接受,但是对于大文件,就接受不全。

另一位朋友的答复:

首先你要明白下载文件的过程机制。我这几天正在写winsock,把我的经验告诉你吧。
1、发送http头:
首先构建最简请求字符串:
dim   httpheader   as   string
httpheader= " "
httpheader=httpheader   &   "get   /images/smilies/wizenflower.gif   http/1.1 "   &   vbcrlf  
httpheader=httpheader   &   "host:   www.vbgood.com "   &   vbcrlf   &   vbcrlf
这样的头就可以了。

然后发送请求:
socks.connect   "www.vbgood.com ",   "80 "

然后在connet事件时:
socks.senddata   httpheader

2、接收数据
这里是关键。服务器返回的数据有2部分组成。一部分是http响应消息头,另一部分是你要下载的文件二进制数据。服务返回的数据不一定是几次,有可能一次,有可能二次,或者n次,而且响应消息头和返回的二进制数据不一定是分开的,有可能是一起返回,有可能第一次返回消息头,第二次返回二进制数据。服务器不同二不同。而且每次返回的数据大小最大是64kb,这是tcp包的最大尺寸。
你接收不到文件的问题就是出在你只接在arrival事件收一次数据,这当然是不全的。你应该首先在响应头中查找content_lenth,确定返回的数据总大小。然后定义一个全程byte()字节数组变量,分多次接收返回的数据,用ubound(byte)判断是否已经接收完全。大概思路就是这样,废话不多说,给你我的代码,我已经测试通过。

我写的是支持多线程(多winsock同时下载的代码),不懂的问。

调用方法:在data_arrival()中  
                dim   databyte()   as   byte     '用字节数组接受数据
                socks.getdata   databyte
                if   savedata(databyte(),   "wizenflower.gif ",   0)   =   false   then   '调用一个winsock(0)
                      ...
                end   if

                if   savedata(databyte(),   "wizenflower.gif ",   1)   =   false   then   '再调用一个winsock(1)
                      ...
                end   if


完整代码如下:
'这是一个支持从网站以http协议下载的模块,支持多线程(winsock)模式。

private   arrival_first_times()   as   boolean         '数据第一次到达
private   f_num()   as   integer   '取得系统的空闲文件号
public   file_lenth()   as   string   '待下载的文件大小
public   received_byte()   as   long   '已接受字节

public   function   savedata(databyte()   as   byte,   filename   as   string,   pros_id   as   integer)   as   boolean
'databyte():接收到的字节数组,filename:要保存的文件名ros_id:线程id,支持多winsock。

'根据线程数定义动态数组的大小(保护原有数据模式)
redim   preserve   arrival_first_times(pros_id   +   1)
redim   preserve   f_num(pros_id   +   1)
redim   preserve   file_lenth(pros_id   +   1)
redim   preserve   received_byte(pros_id   +   1)

on   error   goto   err
if   arrival_first_times(pros_id)   =   false   then   '数据第一次到达的时候,包含消息头,也可能一起包括2进制文件:所以检查消息头,并分离数据

                dim   datastr   as   string
                datastr   =   strconv(databyte(),   vbunicode)   '这里是将字节数组转化为字符串,以便于操作
       
                if   instr(1,   datastr,   "http/1.1   200   ok ")   or   instr(1,   datastr,   "http/1.0   200   ok ")   then   '检查http响应状态
                          '取得待下载的文件大小字节数
                          dim   pos1,   pos2,   title_lenth,   start_pos
                          title_lenth   =   len( "content-length: ")
                          pos1   =   instr(1,   datastr,   "content-length: ")
                          pos2   =   instr(pos1,   datastr,   vbcrlf)
                          file_lenth(pros_id)   =   mid(datastr,   pos1   +   title_lenth,   pos2   -   pos1   -   title_lenth)
                         
                        '从服务器返回的数据中,取得下载文件的起始位置。
                        '说明:消息结束和文件结束的地方,分别用2个换行表示数据结束。一个换行vbcrlf占用2字节。
                        '在字符串中,2个换行就是2个vbcrlf;而在字节数组中,就是连续的databyte(i)=13,databyte(i+1)=10,databyte(i+2)=13,databyte(i+3)=10
                       
                          for   i   =   0   to   ubound(databyte())   -   3   '减3是因为文件的最后也是2个换行,而我们需要的是消息头和文件之间的分割,所以不搜索最后的那2次换行。
                                  if   databyte(i)   =   13   and   databyte(i   +   1)   =   10   and   databyte(i   +   2)   =   13   and   databyte(i   +   3)   =   10   then
                                  start_pos   =   i   +   4   '加4是因为每个换行占用了2个字节,所以往后4个字节,正好是二进制数据开始的地方
                                  exit   for
                                  end   if
                          next
                         
                          '将第一次接受到的字节,除去http响应标题以外的二进制数据,写入文件
                          if   dir(app.path   &   "/ "   &   filename)   <>   " "   then   '第一次写入文件,如果写入之前文件已存在,则删除。
                          kill   app.path   &   "/ "   &   filename
                          end   if
                         
                          f_num(pros_id)   =   freefile()
                          open   app.path   &   "/ "   &   filename   for   binary   lock   write   as   #f_num(pros_id)
                                for   i   =   start_pos   to   ubound(databyte())
                                        put   #f_num(pros_id),   ,   databyte(i)
                                next
                          close   #f_num(pros_id)
                         
                          arrival_first_times(pros_id)   =   true   '已经完成第一批到达数据的处理。
                         
              else
                        savedata   =   false
                        exit   function
              end   if
             
              received_byte(pros_id)   =   received_byte(pros_id)   +   ubound(databyte())   +   1   -   start_pos
             
else   '如果不是第一到达数据,则直接写入文件

                f_num(pros_id)   =   freefile()
                open   app.path   &   "/ "   &   filename   for   binary   lock   write   as   #f_num(pros_id)
                if   lof(f_num(pros_id))   >   0   then   seek   #f_num(pros_id),   lof(f_num(pros_id))   +   1
                put   #f_num(pros_id),   ,   databyte()
                close   #f_num(pros_id)

                received_byte(pros_id)   =   received_byte(pros_id)   +   ubound(databyte())   +   1
end   if

savedata   =   true
exit   function

err:
savedata   =   false

end   function



快速检索

最新资讯
热门点击