I have to make a simple IRC client/server programs for my IT school. The subject asks us to use select(2) for socket polling but forbids us to use O_NONBLOCK sockets.
Your server will accept multiple simultaneous connections.
Attention, the use of fork is prohibited. So you should imperatively use select
Your server must not be blocking.
This has nothing to do with non-blocking sockets, which are prohibited (so do not use fcntl(s, O_NONBLOCK))
I’m wondering if it is even possible to design a non-blocking server (which does not fork) with blocking sockets even using select(2).
Here is a simple example: let say we have a simple text protocol with one command per line. Each client has a buffer. When select(2) tells us a client is ready for read(2), we read until we found a \n in the client buffer, therefor we process the command. With non-blocking sockets, we would read until EAGAIN.
Let imagine now that we are using blocking sockets and a malicious client sends text with no line-break. select(2) tells us data is available, we then read(2) on the client. But we will never read the expected \n. Instead of returning EAGAIN, the syscall will block indefinitely. This is a denial of service attack.
Is it really possible to design a non-blocking server with blocking-sockets and select(2) (no fork(2))?
Yes, you read once from the socket that select tells you is ready. If the read contains the \n, then process that line. Otherwise, store any data that was received, and immediately go back to the select.
This means of course, that for every open socket, you must maintain state information, and a buffer of data read so far. This allows the code to process each read independently, without the need to finish a full line before going back to the select.
It's impossible.
select() blocks, and therefore so does any program that calls it.
The behaviour defined by Posix for send() in blocking mode is that it blocks until all the data supplied has been transferred to the socket send buffer. Unless you're going to delve into low-water marks and so on, it is impossible to know in advance whether there is enough room in he socket send buffer for any given send() to complete without blocking, and therefore impossible for any program that calls send() not to block.
Note that select() doesn't help you with this. It can tell when you when there is some room, but not when there is enough.
Related
I need to "wake up" a process that is waiting on epoll() from another process.
I've created a UDS (AF_UNIX) type SOCK_DGRAM where:
The client every few ms might send one char to the server
The server is waiting with epoll() on the socket for read
I don't need the data from the client, only to "wake up" from it
How can i do this the most efficiently?
Do i have to read() the data?
Can the server somehow ignore the data without overloading the socket's memory?
Do i have to read() the data? Can the server somehow ignore the data without overloading the socket's memory?
If you're receiving data on a socket on an ongoing basis then yes, you need to read that data, else the socket buffer will eventually fill. After it does, you will not receive any more data. You don't need to do anything with the data you read, and you can consume many bytes at a time if you wish, but reading the data is how you remove them from the socket buffer.
You will also find that epoll_wait() does not behave as you want if you do not read the data. If you are watching the socket fd in level-triggered mode, and there are already data available to read, then epoll_wait() will not block. If you are watching the socket fd in edge-triggered mode, and there are already data ready to read, then receiving more data will not cause epoll_wait() to unblock.
How can i do this the most efficiently?
Are you really worried about single-byte read() calls at rate not exceeding one every few milliseconds? Is this for some low-power embedded system?
I don't really see a lot of room for improvement if you've settled on using epoll for this. If it turns out not to perform well enough for you, then you could consider alternatives such as process-shared semaphores or signals, though it is by no means clear that either of these would be superior. This is what performance testing is for.
I'm writing a network application based on an epoll loop and thread pool for handling requests. In each thread I take special care not to block on client reads, by using non-blocking sockets and returning as soon as read returns EAGAIN (or EWOULDBLOCK to be POSIX compliant...).
Should I take special care in socket writes too? I don't see myself sending enough data to fill the system TCP buffers, and blocking for a while shouldn't be too harmful. Is this the only case where a write on a socket blocks? Not enough buffer size?
Also, can a socket be declared non-blocking for reads and blocking for writes? Or should I use fcntl all the time to switch between these behaviours?
Thanks!
The only case where a write on a socket blocks is when the data written won't fit in the buffer. Ideally, you would handle writes much the way you handle reads. You don't need to switch before each write. If you want to block on write, use this logic:
Perform the write.
If it completes, you're done.
Switch the socket to blocking.
Perform the (rest of) the write.
Switch the socket back to non-blocking.
The correct way to handle this is to use non-blocking I/O throughout given that you're using non-blocking reads. When you do a write, if you get -1/EWOULDBLOCK, start selecting on that socket for writeability, and when you get it, retry the write. If that succeeds, stop selecting on writeability for that socket. Don't switch to blocking-mode for that socket, it defeats the whole purpose.
I have to write a chat client-server for a class using unix sockets (without O_NONBLOCK) and select for asynchronous I/O on them. At the moment, on the server, i read 1024 bytes from the client, and directly handle it.
For example, in case of a message, i will receive a command formatted as MSG <msg> (representing a client sending a message), i will go through all the sockets of the connected clients and write the message on them.
This approach actually works but i recently found by reading the man of send that it can blocks if the socket buffer is full and is the flag O_NONBLOCK is not set on the socket.
I think this problem could happen when a client does not read for some reasons (crash, bugged etc.) and this would be critical for my server since it will basically blocks until this client read again.
So here is my question:
What is the correct approach on a potentially blocking socket to avoid send to block if the socket buffer is full?
I'm currently using select only to check if there is something to read on sockets but maybe i should use it also to see if i can write on a particular socket too? And also, can i know how many bytes i can read/write when select returns? For example, if select "tells" that i can write on this socket, how can i know how many bytes i can write at most before writing on this socket actually becomes blocking?
Thanks.
You could use setsockopt() together with SO_SNDTIMEO to set up a maximum amount of time send() will try to do its work.
See man setsockoptand man 7 socket for details.
It might be horrible. If you don't go NONBLOCK-ing mode and calling select(), which internally puts the process on sleep for specific timeout value. That means, fd will be blocked for that specific time period.
This approach actually works but i recently found by reading the man of send that it can blocks if the socket buffer is full and is the flag O_NONBLOCK is not set on the socket.
This is why you use select, but it still isn't reliable, as man select states:
Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has
arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may
be safer to use O_NONBLOCK on sockets that should not block.
The goal is to read data from a socket without blocking. The Linux manual page says:
The receive calls normally return any data available, up to the
requested amount, rather than waiting for receipt of the full amount
requested.
Does it mean that I don't have to pass MSG_DONTWAIT flag to recv() after polling the socket descriptor with select()/poll()/epoll()?
The behaviour of recv/read depends on the characteristics of the socket itself. If the socket is marked as non-blocking, these calls should immediately return EAGAIN/EWOULDBLOCK rather than blocking the process.
The socket can be marked as non-blocking prior to reading from it, usually via fcntl or ioctl.
What this excerpt from the manual says is that, basically, reads on both blocking and non-blocking sockets are not required to fill the whole buffer that is supplied. That is why it is important to check the result of the recv/read calls in order to know how much of the buffer contains the actual data and how much is garbage.
It is not a good idea at all to use blocking sockets in conjunction with the IO polling calls such as select/poll/epoll. Even if the polling call indicates that a particular socket is ready for reading, a blocking socket would sometimes still block.
When a socket is signalled as being OK to write by a call to select(), how can I know how much data I can send without blocking? (In the case of full send buffers etc.)
Does inclusion in the set returned by select() signify that the socket is ready for at least one byte of data, and will send() then return a short count of written bytes?
Or will it block when I call send() with a len parameter that is bigger than the available buffer space? If so, how do I know the maximum amount?
I'm using regular C sockets on Linux.
The send call should not block on the first call, and should send at least one byte on the first call -- assuming you are using a stream protocol and assuming it's not interrupted by a signal, etc. However, there are really only two ways to figure out how much data you can send:
Call select after every call to send to see if more data can be sent.
Put the socket in non-blocking mode, and call send until it gives an EAGAIN or EWOULDBLOCK error.
The second option is preferred. (The third option is to do it in a different thread and simply let the thread block, which is also a good solution. In the past, threading implementations weren't as mature so non-blocking mode was seen as necessary for high-performance servers.)
You cannot know. You have to sent the socket to be non-blocking, and then pay attention to the return value that tells you how much it has written.