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寫文件操作
請高手指點一二!
...全文
231 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
  • 打赏
  • 举报
回复
補充一下,,服務端和客戶端是放到兩台不同的機器上的,,,我在同一台機器上測就沒有這樣的問題出現


一、WinSock简介 Socket(套接字)最初是由加利福尼亚大学Berkeley(伯克利)分校为UNIX操作系统开发的网络通信接口,随着UNIX的广泛使用,Socket成为当前最流行的网络通信应用程序接口之一。20世纪90年代初,由Sun Microsystems,JSB,FTP software,Microdyne和Microsoft等几家公司共同定制了一套标准,即Windows Socket规范,简称WinSock。 VB编写网络程序主要有两种方式:1.winsock控件 2.winsockAPI 二、WinSock控件的使用 1.WinSock控件的主要属性 LocalHostName属性 本地机器名 LocalIP属性 本地机器IP地址 LocalPort属性 本地机器通信程序的端口(0<端口<65536) RemoteHost属性 远程机器名 RemotePort属性 远程机器的通信程序端口 Protocol属性 通过Protocol属性可以设置WinSock控件连接远程计算机使用的协议。可选的协议是TCP和UDP对应的VB的常量分别是sckTCPProtocol和sckUDPProtocol,Winsock控件默认协议是TCP。注意:虽然可以在运行时设置协议,但必须在连接未建立或断开连接后。 SocketHandle属性 返回当前socket连接的句柄,这是只读属性。 RemoteHostIP属性 属性返回远程计算机的IP地址。在客户端,当使用了控件的Connect方法后,远程计算机的IP地址就赋给了RemoteHostIP属性,而在服务器端,当ConnectRequest事件后,远程计算机(客户端)的IP地址就赋给了这个属性。如果使用的是UDP协议那么当DataArrival事件后,发送UDP报文的计算机的IP才赋给了这个属性。 ByteReceived属性 返回当前接收缓冲区中的字节数 State属性 返回WinSock控件当前的状态 常数 值 描述 sckClosed 0 缺省值,关闭。 SckOpen 1 打开。 SckListening 2 侦听 sckConnectionPending 3 连接挂起 sckResolvingHost 4 识别主机。 sckHostResolved 5 已识别主机 sckConnecting 6 正在连接。 sckConnected 7 已连接。 sckClosing 8 同级人员正在关闭连接。 sckError 9   错误 2.WinSock主要方法 Listen方法 方法用于服务器程序,等待客户访问。格式:Winsock对象.listen Connect方法 用于向远程主机发出连接请求。格式:Winsock对象.connect [远程主机IP,远程端口] Accept方法 用于接受一个连接请求。格式:Winsock对象.accept Request ID Senddata方法 用于发送数据。格式:Winsock对象.senddata 数据 Getdata方法 用来取得接收到的数据。格式:Winsock对象.getdata 变量 [,数据类型 [,最大长度]] Close方法 关闭当前连接。格式:Winsock对象.close Bind方法 用Bind方法可以把一个端口号固定为本控件使用,使得别的应用程序不能再使用这个端口。 Listen方法Listen方法只在使用TCP协议时有用。它将应用程序置于监听检测状态。 Connect方法 当本地计算机希望和远程计算机建立连接时,就可以调用Connect方法。Connect方法调用的规范为:Connect RemoteHost,RemotePort Accept方法 当服务器接收到客户端的连接请求后,服务器有权决定是否接受客户端的请求。 SendData方法当连接建立后,要发送数据就可以调用SendData方法,该方法只有一个参数,就是要发送的数据。 GetData方法 当本地计算机接收到远程计算机的数据时,数据存放在缓冲区中,要从缓冲区中取出数据,可以使用GetData方法。GetData方法调用规范如下:GetData

1,502

社区成员

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

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