How to find which socket descriptor had become invalid in fdset - sockets

In the server side while doing select() on readfds it returns bad file descriptor error.How can i find which of the fd has become invalid in fdset?

Usually, when a connection on the other side is closed or an RST segment is sent, select returns and marks the corresponding descriptors as ready for read. When you subsequently perform read/recv from them, an error or EOF is returned.
You might also try using strace tool (if available) for debugging. It will help you keep track of what descriptors are fed to select and what descriptors read/recv are called with.

You can check pending error on a socket with the following function:
int get_socket_error( int s ) {
int error;
socklen_t len = sizeof( error );
if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &error, &len ) < 0 )
error = errno;
return error;
}
But as #Maxim is saying, having EBADF returned from select(2) is usually an indication of a sloppy coding,

Related

How to use the socket select function

I'm trying to understand the socket select function.
The first argument, I've read that nfds can be ignored, should be one more the highest descriptor value and also that it should be max count + 1.
What should that number be?
Also if I've got select fds added via FD_SET(), when select returns...
what's the way to iterate thru all the fds that are set (e.g. readable)
with doing something like
if ( FD_SET(socket1, &fds) )
...
if ( FD_SET(socket2, &fds) )
...
I suppose I could put them in an array - but i was hoping there would be an iterator function.
I've read that nfds can be ignored
Only for WinSock's select() on Windows. For select() on other platforms, nfds is required.
The first argument ... should be one more the highest descriptor value and also that it should be max count + 1.
What should that number be?
Exactly what you just said: "one more the highest descriptor value". So, for instance, if you have just socket1 in the fds, then nfds needs to be socket1 + 1. If you have both socket1 and socket2 in the fds, then nfds needs to be max(socket1, socket2) + 1. And so on, with the more descriptors you add to the fds.
Also if I've got select fds added via FD_SET(), when select returns...
what's the way to iterate thru all the fds that are set (e.g. readable)
There isn't one. At least, not a portable way. You need to test each socket individually, eg:
if ( FD_ISSET(socket1, &fds) ) {
...
}
if ( FD_ISSET(socket2, &fds) ) {
...
}
If you put socket1 and socket2 in an array/list, you can then enumerate that instead, eg:
SOCKET sockets[] = ...;
int numSockets = ...;
for(int i = 0; i < numSockets; ++i) {
if ( FD_ISSET(sockets[i], &fds) ) {
...
}
}
i was hoping there would be an iterator function.
There isn't one.

read long message from client

I am trying to read a long message from the client then print to the server stdout, but when I run the code, the length of the data that is read from client is different almost every time...
I also tried using malloc, but the result was same. I'm really wondering why...
The client code is well made, the problem seems to be on the server side.
Here's the relevant part of the code:
char buf[MAX]; //MAX=1024;
memset(buf, '\0', sizeof(buf));
size_t b;
while ((b = read(connect_fd, buf, MAX - 1)) > 0) {
buf[b] = '\0';
printf("%s", buf);
flush(stdout);
write(coonect_fd, buf, strlen(buf));
memset(buf, '\0', MAX);
}
This read loop seems OK, there could be problems somewhere else, in the server code or in the client code. Here are a few pointers to potential problems:
There is no need to clear the array with memset().
b should be defined as ssize_t to detect read errors and avoid undefined behavior if read() returns -1.
setting the null terminator is not strictly needed: you can use printf("%.*s", (int)b, buf); or fwrite(buf, 1, b, stdout);.
when writing to the coonect_fd, use b instead of strlen(buf).
make sure the client flushes its output the socket.

When can TLM peek fail?

I was working on OVM driver sequencer communication. I am using try_get_item() in ovm driver but it is still getting stuck. In my sequencer I redefined try_next_item and just printed a display statement before and after m_req_fifo.peek(t); The statement before peek got executed but not the statement after the peek. I even displayed size of the m_req_fifo using m_req_fifo.size() and it printed out 1. Why is peek not returning anything even after the size is 1? The modified try_next_item (Just addition of display) is given below.
The line After PEEK never gets executed after the line Line 398 with fifo size 1
virtual task try_next_item(output REQ t);
int selected_sequence;
time arb_time;
ovm_sequence_base seq;
if (get_next_item_called == 1) begin
ovm_report_error(get_full_name(), "get_next_item/try_next_item called twice without item_done or get in between", OVM_NONE);
return;
end
wait_for_sequences();
selected_sequence = choose_next_request();
if (selected_sequence == -1) begin
t = null;
return;
end
set_arbitration_completed(arb_sequence_q[selected_sequence].request_id);
seq = arb_sequence_q[selected_sequence].sequence_ptr;
arb_sequence_q.delete(selected_sequence);
m_update_lists();
sequence_item_requested = 1;
get_next_item_called = 1;
$display("Line 398 with fifo size %0d\n", m_req_fifo.size());
m_req_fifo.peek(t);
$display("After PEEK\n");
wait_for_sequences();
// attempt to get the item; if it fails, produce an error and return
if (!m_req_fifo.try_peek(t))
ovm_report_error("TRY_NEXT_BLOCKED", {"try_next_item: the selected sequence '",
seq.get_full_name(), "' did not produce an item during wait_for_sequences(). ",
"Sequences should not consume time between calls to start_item and finish_item. ",
"Returning null item."}, OVM_NONE);
endtask
uvm_tlm_fifo::size() doesn't return the number of elements in the FIFO, but its capacity (i.e. the maximum number of elements it can hold). The function you're looking for is uvm_tlm_fifo::used() which returns the number of stored elements.
The function names are not intuitive at all and I remember spending a couple of hourse trying to understand some similar code to the one you had until noticing in the documentation that I was using the wrong method.

what could limit bytes read in from read()

I am reading bytes off a socket initialised like this:
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
However when I read from this socket
char buf[ETH_FRAME_LEN]
len = read(fd, buf, sizeof(buf));
len shows only 1500 bytes were read. I checked with wireshark and the packet returned is 5854. The total length field under IP says 5840 (so + 14 bytes for ethernet header = 5854). I tried using a larger buffer (6000) but still only 1500 bytes were being read off the wire.
I tried requesting a smaller file from the server (1504 bytes), but I get the same results. As it is a raw socket, the data read in includes the ethernet headers, so it is not reading the last 4 bytes into the buffer.
What could be the cause of this? I'm not aware of any argument to socket() that could cause this.
What happens if you try calling read again? Is the next chunk of the message quickly returned?
From the read man page (my emphasis)
read() attempts to read up to count bytes
If you want to read a certain number of bytes, you should be prepared to call read in a loop until you receive your target total cumulatively over the calls.
What is happening is that you're getting exactly one Ethernet MTU's worth of payload per call to read().
read() returns:
On success, the number of bytes read is returned (zero indicates end of
file), and the file position is advanced by this number. It is not an
error if this number is smaller than the number of bytes requested;
this may happen for example because fewer bytes are actually available
right now (maybe because we were close to end-of-file, or because we
are reading from a pipe, or from a terminal), or because read() was
interrupted by a signal. On error, -1 is returned, and errno is set
appropriately. In this case it is left unspecified whether the file
position (if any) changes.
You can try to use recv() with MSG_WAITALL instead of pure read():
This flag requests that the operation block until the full
request is satisfied. However, the call may still return less
data than requested if a signal is caught, an error or disconnect occurs, or the next data to be received is of a different
type than that returned.
len = recv(fd, buf, sizeof(buf), MSG_WAITALL);
Another way is to read or recv in a loop like:
ssize_t Recv(int fd, void* buf, ssize_t n)
{
ssize_t read = 0;
ssize_t r;
while(read != n)
{
r = recv(fd, ((char*)buf)+read, n-read, 0);
if(r == -1)
return (read) ? read : -1;
if(r == 0)
return 0;
read += r;
}
return read;
}

Determing the number of bytes ready to be recv()'d

I can use select() to determine if a call to recv() would block, but once I've determined that their are bytes to be read, is their a way to query how many bytes are currently available before I actually call recv()?
If your OS provides it (and most do), you can use ioctl(..,FIONREAD,..):
int get_n_readable_bytes(int fd) {
int n = -1;
if (ioctl(fd, FIONREAD, &n) < 0) {
perror("ioctl failed");
return -1;
}
return n;
}
Windows provides an analogous ioctlsocket(..,FIONREAD,..), which expects a pointer to unsigned long:
unsigned long get_n_readable_bytes(SOCKET sock) {
unsigned long n = -1;
if (ioctlsocket(sock, FIONREAD, &n) < 0) {
/* look in WSAGetLastError() for the error code */
return 0;
}
return n;
}
The ioctl call should work on sockets and some other fds, though not on all fds. I believe that it works fine with TCP sockets on nearly any free unix-like OS you are likely to use. Its semantics are a little different for UDP sockets: for them, it tells you the number of bytes in the next datagram.
The ioctlsocket call on Windows will (obviously) only work on sockets.
No, a protocol needs to determine that. For example:
If you use fixed-size messages then you know you need to read X bytes.
You could read a message header that indicates X bytes to read.
You could read until a terminal character / sequence is found.