winsock接收數據問題

vpdlsr 2007-11-29 02:53:48
服務端代碼:
Do While Not readfile.EOS
getbinary = readfile.Read(8192)
listenchk(Index).SendData getbinary
DoEvents
Loop
Private Sub listenchk_SendComplete(Index As Integer)
Sleep (1000)
End Sub
客戶端代碼:
就是接到數據后寫入文件里

現在問題是當我把服務端那個sleep(1000)去掉或設為更少的單位,客戶端就接收不了數據,,
是不是保在一個發數據太快,一個處理數據太慢啊,,,客戶端只是簡單的用ADODB.STREAM寫文件操作
請高手指點一二!
...全文
229 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
NOVAWU 2007-12-03
  • 打赏
  • 举报
回复
VB6的吧!

延时问题你没考虑吧!
vbman2003 2007-12-03
  • 打赏
  • 举报
回复
结贴点“管理贴子”

还有winsock会有延时现象,这和传输的数据量大小以及硬件网络都有关。其实我对winsock也没太深的了解,都是以前学编程的时候学用过,对于延时有什么好方法处理,还真不知道......
vpdlsr 2007-12-03
  • 打赏
  • 举报
回复
我要給分你怎樣結貼的
vbman2003 2007-12-03
  • 打赏
  • 举报
回复
copymemory是对内存块进行读写操作的,可能是比较消耗资源,不过对大数据的传输效率比较好,上面的过程结束后,所有过程级变量应该是自动释放的
vpdlsr 2007-12-03
  • 打赏
  • 举报
回复
問題已經解決了,,TKS,,,我還有一個問題,,用copymemory是不是會占用內存的,我想發一次就把剛占用的內存釋放掉,有沒有這個方法啊
vpdlsr 2007-12-03
  • 打赏
  • 举报
回复
大大的虾米
請教延時的問題
vpdlsr 2007-12-01
  • 打赏
  • 举报
回复
我一次接到了,
CopyMemory getfiledate(0), getallstr(lenmax - 6), 7

Debug.Print StrConv(getfiledate, vbUnicode)
'Debug.Print UBound(getfiledate)

getend = Trim(StrConv(getfiledate, vbUnicode))

If getend = "fileend" Then
.
.
.
end if
我測度是接到了fileend但是不跑進if里面,我快發瘋了
vbman2003 2007-12-01
  • 打赏
  • 举报
回复
你后面这个代码我觉得可行的,将文件一次性转换为流由winxock分包比你循环转换发送效率要高。不能接收fileend这个问题你可以这样测试:
listenchk(Index).SendData "ABC"
listenchk(Index).SendData "XYZ"
你在接帐端debug.print,结果是“ABCXYZ”,两个字符串一次发送过来了。所以你建议你将getbinary和endbinary打在一个包中发送,到接收端去分离,就如我示例那样处理,试试吧



vpdlsr 2007-12-01
  • 打赏
  • 举报
回复
我還有一個問題
readfile.Type = adTypeBinary

readfile.Open

readfile.LoadFromFile App.Path & "\updateClient\updateClient.rar"

Do While Not readfile.EOS

getbinary = readfile.Read(8192)
listenchk(Index).SendData getbinary
DoEvents
slptime.Item(Index) = GetTickCount
Loop

readfile.Close
Set readfile = Nothing

'字符串轉換為字節流
endbinary = StrConv("fileend", vbFromUnicode)

listenchk(Index).SendData endbinary
DoEvents

我想同時多個人一起下載文件,但是現在這段代碼,有問題,第一個人進來可以收到,每發一次要等一次,但沒發完時第二個人進來了這個就兩個進程讀一個文件有問題了,第一個人收不到,第二個人可以收,呵呵,我把代碼改為
readfile.Type = adTypeBinary

readfile.Open

readfile.LoadFromFile App.Path & "\updateClient\updateClient.rar"

getbinary = readfile.Read()
listenchk(Index).SendData getbinary
DoEvents

readfile.Close
Set readfile = Nothing

'字符串轉換為字節流
endbinary = StrConv("fileend", vbFromUnicode)

listenchk(Index).SendData endbinary
DoEvents

在客和服都在本機我測了可以全接收但"fileend"接收不了,,分開在不同的機器客只收了兩次,,我快急死了,,唉
vpdlsr 2007-12-01
  • 打赏
  • 举报
回复
我的程式和你的是差不多的,,不過我放到兩台分會的機器上就有問題了,,,本機測試沒有問題,,我發現如果服務端把那個sleep(1000)拿掉,客戶端只接收兩次
vpdlsr 2007-12-01
  • 打赏
  • 举报
回复
我打印出来可以接到fileend就是比较的时候有问题

getend = Trim(StrConv(getfiledate, vbUnicode))

If getend = "fileend" Then
.
.
.
end if

这里的getend就是fileend
还有,我把服务端放在我电脑上,把客户端放到另一台机器上,它接不到信息,我不知道为什么,,如果把客户端放到我电脑上就没有问题
你有QQ吗,,我加你,,我的QQ是81290656
vbman2003 2007-12-01
  • 打赏
  • 举报
回复
不要疯,慢慢来,呵呵
你debug.print getend是正确的吗?
vbman2003 2007-11-30
  • 打赏
  • 举报
回复
winsock用TCP传输数据理论是可以保证数据完整的接收和发送的。所以你要做的工作就是构造好数据包,包头用来标识数据包的类型以便分类处理,包尾用来标识结尾,保证接收端接收数据的完整性。下面是个winsock发送接收记录集的简单示例,加了个标志来标识结尾:


Private Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" ( _
Destination As Byte, _
Source As Byte, _
ByVal Length As Long)

'记录集转化为二进制
Public Function RecordsetToBimary(rs As Recordset) As Byte()

Dim stm As Stream

Set stm = New Stream
stm.Open
stm.Type = adTypeBinary
rs.Save stm, adPersistADTG
stm.Position = 0
RecordsetToBimary = stm.Read()
Set stm = Nothing

End Function

'二进制还原为记录集
Private Function BimaryToRecordset(vData() As Byte) As Recordset

Dim stm As Stream
Dim rs As Recordset

Set stm = New Stream
stm.Open
stm.Type = adTypeBinary
stm.Write vData
stm.Position = 0

Set rs = New Recordset
rs.Open stm
Set BimaryToRecordset = rs

Set rs = Nothing
Set stm = Nothing

End Function

'客户端向器发送查询请求:
Private Sub Command1_Click()

Dim strSql As String
strSql = "select * from so limit 1000"
If Winsock1.State = sckConnected Then
Winsock1.SendData strSql
DoEvents
End If

End Sub

'服务器收到查询请求后执行查询,返回数据
Private Sub Winsock1_DataArrival(Index As Integer, ByVal bytesTotal As Long)

Dim strSql As String
Dim arrData() As Byte
Dim arrLength As Long
Dim FinisData() As Byte
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset

Winsock1(Index).GetData strSql, vbString
Set cn = New ADODB.Connection
cn.Open "ODBCName", "as", "123abc"
Set rs = cn.Execute(strSql)
arrData = RecordsetToBimary(rs) '记录集转换成字节数组
arrLength = UBound(arrData)
Set rs = Nothing
Set cn = Nothing
'添加结束标志
FinisData = "`!"
ReDim Preserve arrData(arrLength + 4)
CopyMemory arrData(arrLength + 1), FinisData(0), 4
'向客户端发送数据
Winsock1(Index).SendData arrData
DoEvents

End Sub

'客户端接收返回的数据
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)

Dim tmpData() As Byte
Dim Finis As String, FinisData(3) As Byte '存取结尾标志
Dim rs As Recordset

'当数据超过8k时,winsock会分包发送
'所以要组合结尾前的全部数据
Static rsData() As Byte '记录集数组
Static rsLength As Long
Static iCount As Integer

'tmpData接收数据
Winsock1.GetData tmpData, vbArray + vbByte

'把接收的数据保存在rsData中
If iCount = 0 Then '第一次接收
rsData = tmpData
iCount = 1
Else
ReDim Preserve rsData(rsLength + bytesTotal)
CopyMemory rsData(rsLength + 1), tmpData(0), bytesTotal
End If
rsLength = UBound(rsData) 'rsData的长度

'判断结尾(结尾4个字节)
CopyMemory FinisData(0), rsData(rsLength - 3), 4
Finis = FinisData
If Finis = "`!" Then
'如果是结尾,截断结尾标志数据
ReDim Preserve tmpData(rsLength - 4)
Set rs = BimaryToRecordset(rsData) '还原记录集
'Call DebugPrintRs(rs) '打印结果
Erase rsData
iCount = 0
rsLength = 0
Set rs = Nothing
MsgBox "OK"
End If
End Sub

vpdlsr 2007-11-30
  • 打赏
  • 举报
回复
我測了服務端一次發大于8K的客戶端接收時是接收了多次,不過我在兩台機器測試常常掉失數據,
vbman2003 2007-11-30
  • 打赏
  • 举报
回复
并不是一次只能输入8k,是大于8k的数据要分包,不过这个你不必担心,winsock会自动分包,一会到公司后给你写个示例
vpdlsr 2007-11-29
  • 打赏
  • 举报
回复
每次只能輸八K哦,,一次輸有問題
vbman2003 2007-11-29
  • 打赏
  • 举报
回复
发送记录集数据?你应该将记录集转换为二进制流,加上结尾标志一次性发送。winsock会自动分包,接收端判断到结尾后,再将数据转换为记录集或写入文件
vpdlsr 2007-11-29
  • 打赏
  • 举报
回复
補充一下,,服務端和客戶端是放到兩台不同的機器上的,,,我在同一台機器上測就沒有這樣的問題出現


1,502

社区成员

发帖
与我相关
我的任务
社区描述
VB 网络编程
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧