TCP协议的特点——它不会帮我们区分消息的边界——比如我们分别发送了10K和20K字节的数据出去,到了接收端的缓冲区中,这两条消息将是30K字节的一大块数据,那么,我们怎样区分消息的边界?

解决方案 »

  1.   

    通常区分TCP消息边界有三种方式:
    (1)发送固定长度的消息
    (2)使用Length-leading的消息
    (3)使用消息分隔符。
    参考:
    http://jiezhi.cnblogs.com/archive/2005/08/15/215419.html
      

  2.   

    使用Length-leading的消息 的方式比较高效。
    就是先发送消息长度,然后再发送消息内容。
      

  3.   

    我一般使用Length-leading格式:先发长度,再发消息体.对于比较简单的数据传输使用消息分隔符会更方便.
      

  4.   

    刚看过jiezhi(风满袖) 的blog,受益匪浅!不知各位有没有较好的消息通讯协议让我参考一下,
    我现在准备用xml字符串做消息,在服务器和客户端都会将xml文件反序列化成对象,由于我现在没有一种区分消息边界的机制,所以,有时反序列时会出错,请各位给出个好注意。
      

  5.   

    你发送xml字符串的话,自然可以使用Length-leading的方式。
    发送端:
    1、先将对象序列化得到xml。
    2、将xml转换为byte[]。
    3、得到byte[]的长度后,将长度转换为byte[],通常你用4个字节表示长度足够了,将这个表示长度的byte[]发送出去。
    4、发送xml的byte[]。
    接收端:
    1、接收到表示长度的byte[],从而知道了后面将读取的字节数。
    2、按照此长度从缓冲区中读取字节流。
    3、将字节流转换为字符串。
    4、反序列化。
      

  6.   

    jiezhi(风满袖) :
    发送端首先要把消息发给服务器端,这时服务器是接收端,服务器端经过处理后再发给不同的客户端,这时另外的客户端是接收端,那么,消息的长度应该怎么发那?
    (消息长度)客户端--〉服务器(经过处理,有可能是信息的消息长度)--〉客户端
    对吗?
      

  7.   

    to jiezhi(风满袖) :
    能给我你的联系方式吗?交个朋友msn:netwyh#hotmail.com
      

  8.   

    Const BUFFER_SIZE As Integer = 1024
     Private Sub SendData(ByVal data As String)
            Dim writer As New IO.StreamWriter(client.GetStream)
            writer.Write(data)
            writer.Flush()
     End Sub Private Sub btn_SendFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSendFile.Click
            Dim filestream As IO.FileStream
            Dim readCount As Integer        filestream = New IO.FileStream(txtFileName.Text, IO.FileMode.Open, IO.FileAccess.Read)
            readCount = 1
            SendData(String.Concat("FILE|", filestream.Length()))
            Dim stream As NetworkStream = client.GetStream
            Do While (readCount <> 0)
                readCount = filestream.Read(writeBuffer, 0, BUFFER_SIZE) '一直读完为止
                stream.Write(writeBuffer, 0, readCount)
                stream.Flush()
            Loop
            filestream.Close()
            txtFileName.Text = ""
            btnSendFile.Enabled = False    End Sub
      

  9.   

    '异步读取的方法. Private Sub DoRead(ByVal ar As IAsyncResult)
            Dim BytesRead As Integer
            Dim strMessage As String        Try            BytesRead = client.GetStream.EndRead(ar)
                If BytesRead < 1 Then
                    MarkAsDisconnected()
                    Exit Sub
                End If            If Me.transferStatus = TRANSFER_STATUS.ASCII Then
                    '得到消息
                    strMessage = Encoding.ASCII.GetString(readBuffer, 0, BytesRead)                If strMessage.Split(Chr(124))(0) = "FILE" Then
                        ' FILE消息 
                        ' 设置当前状态是传送二进制数据
                        Me.transferStatus = TRANSFER_STATUS.Binary
                        '取得文件大小 
                        fileSize = CInt(strMessage.Split(Chr(124))(1))
                        '已传送字节数
                        fileWritedSize = 0                    If fileSize <= 0 Then
                            FileNotFind(fileName)
                        Else
                            FileDownBegin(fileName, fileSize)
                            '写入
                            fileStream = New IO.FileStream(fileName, IO.FileMode.OpenOrCreate, IO.FileAccess.Write)
                        End If
                    Else
                        '传消息
                        ProcessCommands(strMessage)
                    End If            Else
                    fileWritedSize = fileWritedSize + BytesRead
                    Me.fileStream.Write(readBuffer, 0, BytesRead)
                    Me.fileStream.Flush()
                    If fileWritedSize >= fileSize Then
                        Me.fileStream.Close()
                        Me.transferStatus = TRANSFER_STATUS.ASCII
                        FileDownEnd(fileName)
                    End If            End If
                client.GetStream.BeginRead(readBuffer, 0, BUFFER_SIZE, AddressOf DoRead, Nothing)
            Catch e As Exception
                MarkAsDisconnected()
            End Try
        End Sub
      

  10.   

    忘了一点东西..
    通过判断这个来识别传过来的是什么..Enum TRANSFER_STATUS
            ASCII = 0
            Binary = 1
    End Enum
      

  11.   

    一般网络传送消息结构为
    消息头(长度固定)
    {
    消息总长度(消息头+消息体长度)
    消息类型
    消息交易号(采用请求与应答对应)
    }
    消息体
    {
    消息要传递的内容
    }
    我感觉这种方式可能比较标准,那位有经验的同仁能不能共享一些你的经验?
    另外,能不能给提供点Socket编程方面的资料?
      

  12.   

    大家还是看看TCP/IP协议,现成的大把的范例。
      

  13.   

    jiezhi(风满袖) :
    给介绍点资料行吗?
    TCP-IP详解,这本书怎么样,行的话我就去买!
      

  14.   

    jiezhi(风满袖) :
    使用Length-leading的方式时我做的测试程序遇到这样的问题,当不同的客户端同时发送消息时,在读取下一条消息的长度时把第三条消息给读取了一半,这个问题怎样解决哪?