使用Wireshark进行调试,在localhost上发送UDP数据包时收到以下错误:
Destination Unreachable (Port Unreachable)
Checksum: 0x0000 (Illegal)
我首先使用
在10000到15000之间的端口上构建我的服务器startServer :: Port -> IO Server
startServer port = withSocketsDo $ do
-- Look up the server address and port information.
addrs <- getAddrInfo (Just $ defaultHints { addrFlags = [AI_PASSIVE] }) Nothing (Just port)
let serverAddress = head addrs
-- Bind to the socket.
sock <- socket (addrFamily serverAddress) Datagram defaultProtocol
bindSocket sock (addrAddress serverAddress)
-- Create the server and run the client send and receive threads.
clients <- newMVar $ createEmptyClients
let server = Server sock port clients
_ <- forkIO $ forever $ receiveClientJoin server
return server
我正在侦听使用
通过UDP连接的新客户端-- | Connected a client to the server.
receiveClientJoin :: Server -> IO ()
receiveClientJoin server = do
print "Receiving"
(msg, _, clSockAddr) <- recvFrom (sSocket server) 4096
print $ "Server received client join message: " ++ msg
我正在使用
连接到客户端的服务器connectToServer port = do
-- Get the server's address and port information.
addrInfo <- getAddrInfo Nothing (Just "localhost") (Just port)
let serverAddr = head addrInfo
sock <- socket (addrFamily serverAddr) Datagram defaultProtocol
sendTo sock "Hello from this client!" (addrAddress serverAddr)
为什么我的客户端的数据包没有找到服务器?
答案 0 :(得分:1)
问题是您正在侦听IPv6地址并尝试连接到IPv4地址。这实际上是一个常见的问题。例如,我在使用commsec
时遇到了此问题。
考虑您发现AddrInfo
:
import Network.Socket
main :: IO ()
main = do
let port = "2474"
addrs <- getAddrInfo (Just $ defaultHints { addrFlags = [AI_PASSIVE] }) Nothing (Just port)
let serverAddress = head addrs
print serverAddress
addrInfo <- getAddrInfo Nothing (Just "localhost") (Just port)
let serverAddr = head addrInfo
print serverAddr
现在输出会因机器而异,但在我的一个同时具有IPv4和IPv6地址的CentOS系统上,输出清楚地显示第二个(连接)地址是IPv6,而第一个(监听)地址是IPv4:
AddrInfo {addrFlags = [AI_PASSIVE], addrFamily = AF_INET, addrSocketType = Stream, addrProtocol = 6, addrAddress = 0.0.0.0:2474, addrCanonName = Nothing}
AddrInfo {addrFlags = [AI_ADDRCONFIG,AI_V4MAPPED], addrFamily = AF_INET6, addrSocketType = Stream, addrProtocol = 6, addrAddress = [::1]:2474, addrCanonName = Nothing}
一种解决方案是通过提示或地址(例如我的评论中的IPv4地址)强制使用特定版本的IP。提示解决方案可能更合适:
-- For servers:
addrs <- getAddrInfo (Just defaultHints { addrFamily = AF_INET6
, addrFlags = [AI_PASSIVE] })
Nothing (Just port)
-- For clients:
addrInfo <- getAddrInfo (Just defaultHints { addrFamily = AF_INET6 })
(Just "localhost") (Just port)