+ -
当前位置:首页 → 问答吧 → Winsock缓冲区大小问题

Winsock缓冲区大小问题

时间:2010-09-28

来源:互联网

windsock缓冲区大小默认为8192字节,尝试用API函数setsocketopt修改,似乎也修改成功了,代码如下:
VB code

    Dim lResult As Long
    Dim bufSize As Long
    bufSize = CLng(1024) * 1024
    lResult = setsockopt(Winsock1.SocketHandle, SOL_SOCKET, SO_RCVBUF, bufSize, 4)
    If (lResult = SOCKET_ERROR) Then
        MsgBox "Error setting SO_RCVBUF option: " & CStr(Err.LastDllError)
    End If
    lResult = setsockopt(Winsock1.SocketHandle, SOL_SOCKET, SO_SNDBUF, bufSize, 4)
    If (lResult = SOCKET_ERROR) Then
        MsgBox "Error setting SO_SNDBUF option: " & CStr(Err.LastDllError)
    End If
    
    bufSize = 0
    lResult = getsockopt(Winsock1.SocketHandle, SOL_SOCKET, SO_RCVBUF, bufSize, 4)
    If (lResult = SOCKET_ERROR) Then
        MsgBox "Error getting SO_RCVBUF option: " & CStr(Err.LastDllError)
    End If
    'bufSize=1024*1024,说明设置成功



发送端是用vc写的程序,也设置了发送缓冲区为1024*1024,可在Winsock1_DataArrival接收大数据包时还是接收到按8192分割的数据包,不知为何?难道对winsock控件缓冲区的修改无效吗?

作者: bodybo   发布时间: 2010-09-28

没人知道吗?

作者: bodybo   发布时间: 2010-09-29

只修改了自己的缓冲区,别人发过来的包你是改不了的举个例子:
两个Socket缓冲区是仓库,你把自己的仓库改为1024*1024这么大了,别人给你的包裹是8192一个包,难道你想要求人家把8192的包拆开再组合吗?那就不是原来的包了

作者: wolfcapita   发布时间: 2010-09-29

改了自己的缓冲区,只能够说自己这边一次性能够接收1024*1024这么大的包而己。

作者: wolfcapita   发布时间: 2010-09-29

DataArrival事件的触发和缓冲区大小无关,因为他的触发过程是和网络协议包的时间有关。
网络接收是这样的,在一定时间(比如500us)内继续收到相对应的数据包,他会将收到的数
据包数据连续的填入缓冲区,但是超出一定时间(比如500us),再异步通讯中他就会触发 
FD_READ 消息产生 DataArrival 事件。除非是连续的包太多,他才会根据缓冲区大小来
产生 DataArrival,但通常情况下,不会有那么好的网络条件在路由或交换队列中全是你一
个人的连续作业包。

作者: SupermanKing   发布时间: 2010-09-29

引用 2 楼 wolfcapita 的回复:
只修改了自己的缓冲区,别人发过来的包你是改不了的举个例子:
两个Socket缓冲区是仓库,你把自己的仓库改为1024*1024这么大了,别人给你的包裹是8192一个包,难道你想要求人家把8192的包拆开再组合吗?那就不是原来的包了

别以为发送端改了缓冲区大小就可以,因为到了底层,还是将数据分成一个一个很小的网络数据包发送的,
因为在硬件层,比如交换机,不可能有那么大的 RAM 来交换那么大量的数据,所以最终还是通过数据交换
协议将数据分割成一个一个很小的数据包在硬件层传输,而且还因为硬件层处理的不只是一个事务,所以
还将这些包按任务队列来分发,在多个小任务交叉执行的时候,看上去好像每个点都能正常同时传输一样,
但是在队列中,如果因为其他的网络信息也需要传输并把任务插入队列,就有可能影响到原来队列中的任务
执行情况,所以对于连续数据包超时产生 FD_READ 消息的时间所包含的已接受缓冲区数量也未必全部相同,
特别是在 Internet 的网络环境中这个问题就特别体现得严重。

作者: SupermanKing   发布时间: 2010-09-29

这是我在VB中写的Sock类的一个Send方法,你看看过程就知道什么回事了,
在硬件层的交换,把整个数据还要再分包,那就是正真的网络数据包了。
VB code

'==============================================================================
'类方法定义及处理过程
'==============================================================================
'********************************************************************************
'**   方 法 名 :    SendData
'**   输    入 :    data(Variant)      -  要通过Sock发送的任何类型数据内容
'**   返    回 :    无
'**   功能描述 :    发送网络数据
'********************************************************************************
Public Sub SendData(data As Variant)
   Dim SendBuffers() As Byte
   Dim SendBuffersSize As Long
   Dim CancelERR As Boolean
   Dim DataSize As Long
   Dim SockSendCount As Long
   Dim SockSendBuffers() As Byte
   Dim rd As Long
   '将要发送的数据进行字节流格式化
   Select Case VarType(data)
   Case vbString: SendBuffers = StrConv(data, vbFromUnicode)
   
   Case vbArray + vbByte:
                  SendBuffers = data
   End Select
   SendBuffersSize = UBound(SendBuffers) + 1
   '取得发送缓冲区大小
   rd = api_getsockopt(mvarSocketHandle, _
                       SOL_SOCKET, _
                       SO_SNDBUF, _
                       DataSize, _
                       4)
   If rd = SOCKET_ERROR Then
      CancelERR = False
      RaiseEvent SockError(35756, _
                           "不能完成请求。", _
                           0, _
                           "WinSock.SendData.getsockopt", _
                           "", _
                           0, _
                           CancelERR)
      If CancelERR = False Then
         Err.Raise vbObjectError + 35756, "不能完成请求。", 35756, "", 0
      End If
      Exit Sub
   End If
   
   '发送TCP数据
   SendMaxSize = DataSize
   SendNowSize = 0
   If SendBuffersSize <= DataSize Then
      '发送的内容小于或等于Sock发送缓冲区的大小,所以进行一次性发送数据
      rd = api_send(mvarSocketHandle, SendBuffers(0), SendBuffersSize, 0&)
      If rd = SOCKET_ERROR Then
         mvarState = sckError
         CancelERR = False
         RaiseEvent SockError(35756, _
                              "不能完成请求。", _
                              0, _
                              "WinSock.SendData.send", _
                              "", _
                              0, _
                              CancelERR)
         If CancelERR = False Then
            Err.Raise vbObjectError + 35756, "不能完成请求。", 35756, "", 0
         End If
         Exit Sub
      End If
      RaiseEvent SendComplete
   Else
      '自动分包发送数据
      SockSendCount = 0
      SendMaxSize = SendBuffersSize
      ReDim SockSendBuffers(DataSize - 1)
      Do
         CopyMemory SockSendBuffers(0), SendBuffers(SockSendCount), DataSize
AfreshSendData:
         rd = api_send(mvarSocketHandle, SockSendBuffers(0), DataSize, 0&)
         If rd = SOCKET_ERROR Then
            '出错重发
            GoTo AfreshSendData
         ElseIf rd = DataSize Then
            '发送成功
         Else
            mvarState = sckError
            CancelERR = False
            RaiseEvent SockError(35756, _
                                 "不能完成请求。", _
                                 0, _
                                 "WinSock.SendData.send", _
                                 "", _
                                 0, _
                                 CancelERR)
            If CancelERR = False Then
               Err.Raise vbObjectError + 35756, "不能完成请求。", 35756, "", 0
            End If
            Exit Sub
         End If
         SockSendCount = SockSendCount + DataSize
         SendNowSize = SockSendCount
         
         'RaiseEvent SendProgress(SendNowSize, SendBuffersSize)
         If SockSendCount >= SendBuffersSize Then
            DataSize = 0
         Else
            If SockSendCount + DataSize >= SendBuffersSize Then
               DataSize = (SendBuffersSize - SockSendCount)
            End If
         End If
      Loop While DataSize > 0
      RaiseEvent SendComplete
   End If

End Sub

作者: SupermanKing   发布时间: 2010-09-29

热门下载

更多