7

I'm still learning the basics of Haskell and currently working through porting some Java code to Haskell. My current problem is in UDP recvFrom using Network.Socket.ByteString.

The problem is with this method:

public abstract SocketAddress receive(ByteBuffer dst) throws IOException

Receives a datagram via this channel.
If a datagram is immediately available, or if this channel
is in blocking mode and one eventually becomes available,
then the datagram is copied into the given byte buffer and
its source address is returned. If this channel is in
non-blocking mode and a datagram is not immediately available
then this method immediately returns null.

The thing is that when I use Network.Socket.ByteString.recvFrom my code blocks at this point waiting for the packet to come. It doesn't return something like Maybe to indicate if something was received or not (the same way in Java there is a null returned when no data was available)

I found this thread: https://mail.haskell.org/pipermail/haskell-cafe/2010-August/082725.html

At the end of it there are a couple of ways suggested: 1) FFI 2) run recvFrom in its own thread

I'm not sure I'm capable of using any of those approaches at this moment (not enough knowledge). What I want is to get something similar to Java way of non-blocking receive: get needed info if it is available or just nothing if there is no single UDP packet. Anyone can point out what would be a better approach, any code snippets, someone already handled this problem?

ksaveljev
  • 550
  • 2
  • 16
  • 1
    See also [How can I watch multiple files/socket to become readable/writable in Haskell?](http://stackoverflow.com/q/11744527/791604); though I understand that restructuring during a port can be quite disruptive and dangerous. Long-term, doing the receive on its own thread is the right solution, though. You could communicate with the separate thread in a non-blocking way, of course. – Daniel Wagner Apr 14 '15 at 17:06

1 Answers1

4

You could use socketToHandle together with hGetNonBlocking:

recvNonBlocking :: Socket -> Int -> IO ByteString
recvNonBlocking s n = do
     hnd <- socketToHandle s ReadMode 
     hGetNonBlocking hnd n

However, keep in mind that you cannot use the Socket after a call to socketToHandle, so this is only feasible if you would close the Socket either way afterwards.

Zeta
  • 103,620
  • 13
  • 194
  • 236
  • [Note](http://hackage.haskell.org/package/bytestring-0.10.0.2/docs/Data-ByteString.html#v:hGetNonBlocking): on Windows and with Haskell implementation other than GHC, this function does not work correctly; it behaves identically to hGet. – palik Feb 11 '19 at 14:08