lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Tue, Apr 23, 2013 at 9:07 PM, William Ahern <william@25thandclement.com> wrote:
On Tue, Apr 23, 2013 at 08:15:24PM -0400, Rena wrote:
> On Tue, Apr 23, 2013 at 7:53 PM, William Ahern
> <william@25thandclement.com>wrote:
<snip>
> Yes, by listening I meant able to receive packets, sorry for the confusion.
> Am I correct in understanding that a single message sent by a peer will
> always arrive as a single message at the listening application?

Yes. UDP preserves message boundaries, and it will always arrive (if it
arrives, and if it's not dropped by the UDP stack) as a single message, and
will be dequeued in a single call to recv, recvfrom, or read.

> Actually, that still doesn't make it perfectly clear how *a should work
> with UDP, since the peer itself might split its message into several
> pieces.

If the _application_ peer splits its logical message into several pieces,
then of course each individual piece will be received atomically by the
recipient, possibly interleaved with other pieces by other senders. Your
application "pieces" are messages as far as UDP is concerned.

A "message" in UDP is functionally equivalent to a single send or recv call,
not whatever your application defines it as. If the application requires
logical messaging which span multiple send calls, then it needs to implement
an additional layer of framing at both end points.

I'd prefer to abstain from using ambiguous OSI layering terminology, but you
can think of UDP as layer 4, and your logical framing as something higher
than layer 4. If your logical framing isn't satisfied by UDP itself, then
you need to implement it separately.

> It seems like blindly reading until the socket is closed in this situation
> would be a great way to let other peers interfere with the transmission...

If you mean flooding, then yes it could be a problem, but usually only if
done deliberately, in which case you may have other problems. But barring
address spoofing and bandwidth issues, it doesn't by itself cause problems
unless the application makes unwarranted assumptions.

You can always use connect(2) to create an association between two UDP end
points. The kernel will then drop messages for you, so you don't have to
check the IP address.



Well flooding would be one way, but I was thinking more of a communication between two systems using UDP, and a malicious third party just starts sending some of its own packets to one of the clients on that same port; if you just read everything until the socket is closed, disregarding who it came from, and return it all as one string, the third party could inject some malicious packets into the stream. But you're right, that would be a silly way to do things... of course, writing a general-purpose socket library and not a particular application, you have to be ready for the possibility that someone wants to use your library to communicate with a client that does silly things like that.

I wasn't aware you could use connect() on a UDP socket. So, would it be done like this?

void processMessage(char *buffer, ssize_t size) { ... }

int done = 0;
int sockfd = socket(SOCK_DGRAM, AF_INET, 0);
bind(sockfd, AF_INET, someAddress, somePort);

char buffer[8192];
struct sockaddr_in peer;
socklen_t peer_len = sizeof(peer);
ssize_t recvsz = recvfrom(sockfd, buffer, sizeof(buffer), 0,
    (struct sockaddr*)&peer, &peer_len);

processMessage(buffer, recvsz);
connect(sockfd, peer.sin_addr, peer.sin_port);

while(!done) {
    recvsz = recv(sockfd, buffer, sizeof(buffer), 0);
    processMessage(buffer, recvsz);
}

or am I still missing something?

--
Sent from my Game Boy.