fad*_*bee 6 haskell unpack protocol-buffers
我已经构建了一个小型的UDP/protobuf发送器和接收器.我花了一个上午的时间试图找出protobuf解码产生错误的原因,结果却发现发送器(Spoke.hs)发送的数据不正确.
用于unpack
将Lazy.ByteStrings转换为网络包将发送的字符串的代码.我unpack
在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"]
Run Code Online (Sandbox Code Playgroud)
虽然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
Run Code Online (Sandbox Code Playgroud)
Spoke.hs和Wireshark的长度(45)是相同的.
Wireshark缺少最后一个字节(值0x01),中心值流不同(在Wireshark中大一个字节).
"65","10","d2","9"
在Spoke.hs和65:10:c3:92:09
Wireshark中.
由于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 ()
Run Code Online (Sandbox Code Playgroud)
我看到的 bytestring 包的文档将 unpack 列为将 a 转换ByteString
为[Word8]
,这与 a 不同String
。我期望ByteString
和之间存在一些字节差异,String
因为String
Unicode 数据 whileByteString
只是一个有效的字节数组,但首先unpack
不应该生成 a 。String
因此,您可能在这里遇到了 Unicode 转换的问题,或者至少有些东西将其解释为 Unicode,而底层数据实际上不是 Unicode,而且很少有好的结果。
归档时间: |
|
查看次数: |
673 次 |
最近记录: |