我已经构建了一个小型的UDP / protobuf发送器和接收器.我花了一个上午的时间试图找出protobuf解码产生错误的原因,结果却发现发送器(Spoke.hs)发送的数据不正确. 使用解压缩的代码将Lazy.B
使用解压缩的代码将Lazy.ByteStrings转换为网络包将发送的字符串.我在Hoogle发现了解压缩.它可能不是我正在寻找的功能,但它的描述看起来合适:“O(n)将ByteString转换为字符串.”
Spoke.hs产生以下输出:
chris@gigabyte:~/Dropbox/haskell-workspace/hub/dist/build/spoke$./spoke 45 45 ["a","8","4a","6f","68","6e","20","44","6f","65","10","d2","9","1a","10","6a","64","6f","65","40","65","78","61","6d","70","6c","65","2e","63","6f","6d","22","c","a","8","35","35","35","2d","34","33","32","31","10","1"]
虽然wireshark告诉我数据包中的数据是:
0a:08:4a:6f:68:6e:20:44:6f:65:10:c3:92:09:1a:10:6a:64:6f:65:40:65:78:61:6d:70:6c:65:2e:63:6f:6d:22:0c:0a:08:35:35:35:2d:34:33:32:31:10
Spoke.hs和Wireshark的长度(45)是相同的.
Wireshark缺少最后一个字节(值0x01),中心值流不同(在Wireshark中大一个字节).
Spoke.hs中的“65”,“10”,“d2”,“9”与Wireshark中的65:10:c3:92:09.
由于0x10是DLE,它让我感到震惊,可能正在进行一些转义,但我不知道为什么.
我对Wireshark有多年的信任,只有几十个小时的Haskell经验,所以我认为这是错误的代码.
任何建议赞赏.
-- Spoke.hs: module Main where import Data.Bits import Network.Socket -- hiding (send, sendTo, recv, recvFrom) -- import Network.Socket.ByteString import Network.BSD import Data.List import qualified Data.ByteString.Lazy.Char8 as B import Text.ProtocolBuffers.Header (defaultValue, uFromString) import Text.ProtocolBuffers.WireMessage (messageGet, messagePut) import Data.Char (ord, intToDigit) import Numeric import Data.Sequence ((><), fromList) import AddressBookProtos.AddressBook import AddressBookProtos.Person import AddressBookProtos.Person.PhoneNumber import AddressBookProtos.Person.PhoneType data UDPHandle = UDPHandle {udpSocket :: Socket, udpAddress :: SockAddr} opensocket :: HostName -- ^ Remote hostname, or localhost -> String -- ^ Port number or name -> IO UDPHandle -- ^ Handle to use for logging opensocket hostname port = do -- Look up the hostname and port. Either raises an exception -- or returns a nonempty list. First element in that list -- is supposed to be the best option. addrinfos <- getAddrInfo Nothing (Just hostname) (Just port) let serveraddr = head addrinfos -- Establish a socket for communication sock <- socket (addrFamily serveraddr) Datagram defaultProtocol -- Save off the socket, and server address in a handle return $UDPHandle sock (addrAddress serveraddr) john = Person { AddressBookProtos.Person.id = 1234, name = uFromString "John Doe", email = Just $uFromString "jdoe@example.com", phone = fromList [ PhoneNumber { number = uFromString "555-4321", type' = Just HOME } ] } johnStr = B.unpack (messagePut john) charToHex x = showIntAtBase 16 intToDigit (ord x) "" main::IO() main = do udpHandle <- opensocket "localhost" "4567" sent <- sendTo (udpSocket udpHandle) johnStr (udpAddress udpHandle) putStrLn $show $length johnStr putStrLn $show sent putStrLn $show $map charToHex johnStr return ()我在bytestring包中看到的文档列出了解压缩为将ByteString转换为[Word8],这与String不同.我希望ByteString和String之间有一些字节差异,因为String是Unicode数据,而ByteString只是一个有效的字节数组,但是unpack不应该首先生成一个String.
所以你可能会在这里犯下Unicode转换,或者当底层数据真的没有并且很少结束时,至少会把它解释为Unicode.