While searching in the Linux manual page, what I have found about the format of send and recv in socket is like below:
For send,
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
For recv,
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
But I am not sure what they are trying to tell about int flags. In one sample code I have found the value of flag as 0 (zero). What it means? Also what is the meaning of the line below in the man page?
"The flags argument is the bitwise OR of zero or more of the following flags."
Then the list of flags:
MSG_CONFIRM
MSG_DONTROUTE
.
.
.
etc.
if int flags are equal to 0, it means that no flags are specified. these are optional.
to answer about ORing flags - it is a mechanism that allow you to specify more than one flag - MSG_CONFIRM | MSG_DONTWAIT specify two flags.
OR gate: AND gate:
a b out a b out
0 0 0 0 0 0
0 1 1 0 1 0
1 0 1 1 0 0
1 1 1 1 1 1
what i understand, is that by ORing flags you set specific bits to 1 in an int variable.
later in the code, by ANDing that variable with specific flags you know whether flag was set or not.
if you had specified MSG_DONTWAIT flag, the code: flags & MSG_DONTWAIT will return 1, so you know that flag was set.
let's have a look how MSG_DONTWAIT is defined.
enum
{
...
MSG_DONTWAIT = 0x40, /* Nonblocking IO. */
#define MSG_DONTWAIT MSG_DONTWAIT
...
};
the hex notation 0x40 means that only 7th bit is set to 1.
below i present an example of bitwise operations from socket.c. there's a check whether O_NONBLOCK flag was set when socket file descriptor was created. if so, then set on current flags variable 7th bit to 1, which was defined as MSG_DONTWAIT.
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
a nice reference about bitwise operations: http://teaching.idallen.com/cst8214/08w/notes/bit_operations.txt
Flags allow to pass extra behavior. The default value (0) will lead to the default behavior. In most of the simple cases that's what you want.
If you want the network subsystem to behave in a specific way you can pass on flag value or several values by Oring them: For example If you want to have the 'MSG_DONTWAIT' and the 'MSG_MORE' behaviour (as described by the man page) you can use MSG_DONTWAIT | MSG_MORE.
Here's a good explanation, with an example.
The 0 flag allows you to use a regular recv(), with a standard behavior.
If you want to use a custom recv(), you need to separate your flags (thoses who're listed in the man page) with the OR operator, as it's stated here :
"The flags argument is the bitwise OR of zero or more of the following flags."
Just like that :
recv(sockfd, buf, buflen, FLAG | FLAG | FLAG);
Related
I have this peice of code that should read from a pseudo terminal and print to another pseudo terminal (stdin):
// Declare & define a file descriptor.
int fd;
int status;
char string[] = "XXXX";
char buffer[8];
// Establish connection between a file and the file descriptor.
fd = open("/dev/pts/4", O_RDWR);
// Check if connection was established.
if(fd == -1){
printf("Assigning failed: %s\n", strerror(errno));
}
else{
fputs("Assigning successful!\n", stdout);
// Set some flags for the connection.
fcntl(fd, F_SETFL, 0);
}
// Read from the connection.
status = read(fd, buffer, 8);
if (status == -1){
printf("Read failed: %s\n", strerror(errno));
}
else{
printf("I read this: %s\n", buffer);
}
return 0;
I don't know exactly what fcntl(fd, F_SETFL, 0); does, but untill I used it I wasn't able to read from the /dev/pts/4. After I used it for the first time I could read normaly, even if I commented out this line of code.
I tried to explain it to myself reading POSIX...
F_SETFL flag is defined in the POSIX as:
Set the file status flags, defined in <fcntl.h>, for the file
description associated with fildes from the corresponding bits in the
third argument, arg, taken as type int. Bits corresponding to the file
access mode and the file creation flags, as defined in <fcntl.h>, that
are set in arg shall be ignored. If any bits in arg other than those
mentioned here are changed by the application, the result is
unspecified. If fildes does not support non-blocking operations, it is
unspecified whether the O_NONBLOCK flag will be ignored.
So it sets file status flags asociated with the 1st argument (file descriptor) of fnctl() to 0? I found an explanation about the status flags in the POSIX:
The <fcntl.h> header shall define the following symbolic constants for
use as file status flags for open(), openat(), and fcntl(). The values
shall be suitable for use in #if preprocessing directives.
O_APPEND Set append mode. O_DSYNC Write according
to synchronized I/O data integrity completion. O_NONBLOCK
Non-blocking mode. O_RSYNC Synchronized read I/O
operations. O_SYNC Write according to synchronized I/O
file integrity completion.
So does fcntl(fd, F_SETFL, 0); set all those to 0? Are all of those flags a single bit? How do I only set one of them to 1 or 0? And how do I know which bit is assigned to which flag?
It's a bitmask. Each flag is a bit (or several bits) in the integer you pass to fcntl. Each symbolic constant expands to a number in which only the corresponding bit(s) is set, and so you can set several flags by ORing them together. For instance, if bit 2 is the append flag, then O_APPEND would be 0b100 == 4; if bit 3 is the nonblock flag, then O_NONBLOCK would be 0b1000 == 8, and so on. But by using the symbolic constants, you don't need to know which bits they actually are, which is good since they may vary between OSes.
In fcntl(fd, F_SETFL, 0), the number 0 has no bits set, so all the flags are cleared. To set append and clear the rest, you could do fcntl(fd, F_SETFL, O_APPEND);. To set both append and nonblock, OR their constants together: fcntl(fd, F_SETFL, O_APPEND | O_NONBLOCK);
With similar bit operations, you can operate on the flags returned by fl = fcntl(fd, F_GETFL):
int fl = fcntl(fd, F_GETFL);
if (fl & O_APPEND) { ... } // test if in append mode
fcntl(fd, F_SETFL, fl | O_NONBLOCK); // turn on nonblock and keep everything else the same
fcntl(fd, F_SETFL, fl & ~O_DSYNC); // turn off dsync and keep everything else the same
There's some more examples here.
I'm using WSAPoll for my project. I used tracking POLLIN and POLLOUT events. Everything worked nice. When I add POLLHUP as event, WSAPoll returns error 10022 (Invalid argument).
I've no idea what's wrong, please guide me how to fix it:(
cc_qnt - quantity of connected clients
int ev_cnt = WSAPoll(pfd, cc_qnt + 1, 100);
if (ev_cnt > 0) {
for (i = 0; i < cc_qnt; i++) {
if (pfd[i].revents & POLLHUP) {
// some code
}
if (pfd[i].revents & POLLIN) {
// some code
}
}
if (pfd[cc_qnt].revents & POLLIN) {
In this part we have new connection ready for accepting. We edit pfd[cc_qnt] adding new socket (returned by accept) instead of listening socket. Then we reallocate pfd with size + 1, copying previous data and adding listening socket at the end of cc array.
int addrlen = sizeof(addr);
cc[cc_qnt].s = accept(ls, (struct sockaddr*) &addr, &addrlen);
cc[cc_qnt].ip = ntohl(addr.sin_addr.s_addr);
cc[cc_qnt].sent_put = 0;
cc[cc_qnt].c_cl_cn = 0;
pfd[cc_qnt].fd = cc[i].s;
pfd[cc_qnt].events = POLLIN | POLLOUT | POLLHUP;
cc_qnt++;
pfd = init_pfd(pfd, ls, cc_qnt);
}
}
else if (ev_cnt < 0) {
exit(printf("\nprocess_events: WSAPoll, ev_cnt = %d, WSAGetLastError: %d \n", ev_cnt, WSAGetLastError()));
}
Everything I changed for tracking POLLHUP - adding it's bit to pfd[cc_qnt].events and WSAPoll started returning error. I expect tracking POLLHUP event.
Per the WSAPoll() documentation:
WSAEINVAL
An invalid parameter was passed. This error is returned if the fdarray parameter contains a NULL pointer. This error is also returned if invalid flags were specified in the events member of any of the WSAPOLLFD structures pointed to by the fdarray parameter when requesting socket status. This error is also returned if none of the sockets specified in the fd member of any of the WSAPOLLFD structures pointed to by the fdarray parameter were valid.
And per the WSAPOLLFD documentation:
events
Type: short
A set of flags indicating the type of status being requested. This must be one or more of the following.
POLLPRI
Priority data may be read without blocking. This flag is not supported by the Microsoft Winsock provider.
POLLRDBAND
Priority band (out-of-band) data can be read without blocking.
POLLRDNORM
Normal data can be read without blocking.
POLLWRNORM
Normal data can be written without blocking.
The POLLIN flag is defined as the combination of the POLLRDNORM and POLLRDBAND flag values. The POLLOUT flag is defined as the same as the POLLWRNORM flag value.
So, as you can see, POLLHUP is not documented as being a valid flag for input to WSAPoll(). Indeed, it does not match any of the above flags defined in winsock2.h:
/* Event flag definitions for WSAPoll(). */
#define POLLRDNORM 0x0100
#define POLLRDBAND 0x0200
#define POLLIN (POLLRDNORM | POLLRDBAND)
#define POLLPRI 0x0400
#define POLLWRNORM 0x0010
#define POLLOUT (POLLWRNORM)
#define POLLWRBAND 0x0020
#define POLLERR 0x0001
#define POLLHUP 0x0002
#define POLLNVAL 0x0004
POLLHUP is, however, documented as an output flag in the revents member of WSAPOLLFD:
revents
Type: short
A set of flags that indicate, upon return from the WSAPoll function call, the results of the status query. This can a combination of the following flags.
...
POLLHUP
A stream-oriented connection was either disconnected or aborted.
...
This matches the use of POLLHUP in poll() on *nix platforms:
POLLHUP
Hang up (only returned in revents; ignored in events). Note
that when reading from a channel such as a pipe or a stream
socket, this event merely indicates that the peer closed its
end of the channel. Subsequent reads from the channel will
return 0 (end of file) only after all outstanding data in the
channel has been consumed.
So, you don't need to (and on Windows, you cannot) explicitly request POLLHUP, you just get it for free.
I am starting serial port programming in Linux. After reading several examples on the web, I don't understand exact effect of fcntl(fd, F_SETFL, 0)? It is clearing bits, but what flags does it affect? What does it set and or clear?
Take one by one
1) Function call used
fcntl() - It perform the operation on file descriptor passed in argument.
2) 2nd argument in call
F_SETFL (int)
Set the file status flags to the value specified by arg. File access
mode (O_RDONLY, O_WRONLY, O_RDWR) and file creation flags (i.e.,
O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored. On Linux this
command can change only the O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME,
and O_NONBLOCK flags.
3) 3rd argument in call
It is 0 means, It set file status flag to zero.
As Jean-Baptiste Yunès said in comment.
file access mode and file creation flags are ignored. This command
reset every other flags: no append, no async, no direct, no atime, and
no nonblocking
So finally
fcntl(fd, F_SETFL, 0)
This call will set opened file desciptor's file status flag to value 0.
But idealy this way we should not change file status flag.
Best way is to first get the current file status flag using F_GETFL and then just change required bit in that.
See example:
If you want to modify the file status flags, you should get the current flags with F_GETFL and modify the value. Don’t assume that the flags listed here are the only ones that are implemented; your program may be run years from now and more flags may exist then. For example, here is a function to set or clear the flag O_NONBLOCK without altering any other flags:
/* Set the O_NONBLOCK flag of desc if value is nonzero,
or clear the flag if value is 0.
Return 0 on success, or -1 on error with errno set. */
int
set_nonblock_flag (int desc, int value)
{
int oldflags = fcntl (desc, F_GETFL, 0);
/* If reading the flags failed, return error indication now. */
if (oldflags == -1)
return -1;
/* Set just the flag we want to set. */
if (value != 0)
oldflags |= O_NONBLOCK;
else
oldflags &= ~O_NONBLOCK;
/* Store modified flag word in the descriptor. */
return fcntl (desc, F_SETFL, oldflags);
}
per the man page for fcntl()
F_SETFL (int)
Set the file status flags to the value specified by arg. File
access mode (O_RDONLY, O_WRONLY, O_RDWR) and file creation
flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are
ignored. On Linux this command can change only the O_APPEND,
O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK flags. It is not
possible to change the O_DSYNC and O_SYNC flags; see BUGS,
below.
This is from the man page.
Checking the access mode of the file is slightly more complex, since the O_RDONLY (0), O_WRONLY (1), and O_RDWR (2) constants don’t correspond to single bits in the open file status flags. Therefore, to make this check, we mask the flags value with the constant O_ACCMODE, and then test for equality with one of the constants:
accessMode = flags & O_ACCMODE;
if (accessMode == O_WRONLY || accessMode == O_RDWR)
printf("file is writable\n");
I want to understand how the expressiin flags & O_ACCMODE work
Sorry for bad formatting i'm writing from my phone
The file modes are mutually exclusive. You can't be read-only and write-only, and you can't be read-write and either of the other two.
O_ACCMODE is equal to 3 so bits 1 and 2 are on.
00000000 (O_RDONLY)
& 00000011 (O_ACCMODE)
--------
00000000 <-- the result being compared
where 00000000 equals read-only so (accessMode == O_RDONLY) returns true.
The same for the others.
00000001 (O_WRONLY)
& 00000011 (O_ACCMODE)
---------
00000001 <-- the result being compared
O_WRONLY is 1 so (accessMode == O_WRONLY) is "is 1 equal to 1" which naturally returns true.
I don't think the above answer given by #Duck here is correct. Given the examples it makes no sense to mask them.
The reason you need to mask is that
flags = fcntl(fd, F_GETFL);
returns more than just these two bits. In fact the return value could be something like this:
1000000000000001
for write only file.
We mask in order to get rid of those other bits, which are not related to the read/write permissions.
In this O_ACCMODE is used as and mask to get access mode bits.
I'm working on a networking assignment and we are tasked with creating a remote file access server with a protocol we were given. My difficulties come in the lack of information I can find that explains the process of calculating the bits for the oflag argument in open().
I receive a message from a client to open a file and in the message I parse characters for the flags to use in oflag. Specifically they are:
R - O_RDONLY
W - O_WRONLY
RW - O_RDWR
A - O_APPEND
C - O_CREAT
T - O_TRUNC
E - O_EXCL
I went around Google and searched bitwise operations, enumeration flags, bit flags, calculating bit flags, etc. and couldn't find something that was useful in figuring out how to create the bits for oflag. Maybe I just didn't know what I was looking for and overlooked useful information?
Could someone please:
Point me in the direction/provide links to documentation/example of how to calculate the bits/# I ought to put into oflags given my parsed characters or
Show me the enumeration types for the flags and the ordering they ought to go in
Thanks a bunch for you help and if I wasn't clear on my problem or what I am trying to do, just let me know and I will clarify ASAP.
The O_... flags are numbers each with a different single bit set. For example on my system they are defined in fcntl.h as
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100 /* not fcntl */
#define O_EXCL 0200 /* not fcntl */
#define O_NOCTTY 0400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */
#define O_APPEND 02000
You use | (logical OR) to combine the flags and pass in a single number to open with all the bits set for each option you want. So e.g. open("file", O_RDWR | O_CREAT).
You can compute an int and pass that into open too if you want.
int flags = 0;
if (...)
flags |= O_RDWR;
...
open('file', flags);
The usual expression would be something like O_RDWR | O_CREAT. And note that O_RDWR is exactly O_RDONLY | O_WRONLY
You can do something like this:
char *flags = "r";
int oflag = 0;
if (strchr(flags,'r')) oflag |= O_RDONLY;
and so on for the rest of the flags.