If I am writing to a socket file descriptor using write() bytes by bytes,
Is every byte now a packet?
will the socket add TCP/IP header to every byte?
Or does it have a buffer mechanism (I personally doubt so since I don't have explicitly flush).
For example:
write(fd, 'a', 1);
write(fd, 'b', 1);
write(fd, 'c', 1);
Will this be less efficient than say
write (fd, 'abc', 3);
I have to ask this here because I do not have the expertise to monitor TCP/IP header in traffic. Thanks.
No, not every byte will become a packet. Some may be coalesced due to Nagle's Algorithm and other things. There will be one TCP header per packet, not per byte.
That said, you should avoid calling write/send byte by byte because each one is a system call, which is expensive (on the local machine, not in terms of how it ends up on the network).
Adding to John's answer, you can disable Nagle's Algorithm (via TCP_NODELAY) and then the first version will become slower.
And for the reverse, you can call writev() instead of write(), which will cause the first version to perform exactly as the second.
It really depends on the implementation of the TCP/IP stack. It would really depend on the segmentation that is implemented in the OS. Most OSes have a lot of optimization already built in.
If you're looking at a worst case situation, a TCP header is 20 bytes, an IP header is 20 bytes and the size of the frame header (depending on the protocol you're using, probably ethernet), so you could expect that plus your payload. That being said, the majority of the traffic in the internet is dominated by ACKs however, your network stack should combine the payloads.
Related
My question is mainly educational so please don't tell me you shouldn't do that or you should do that. Thanks.
This is basically about how TCP works.
I'm implementing a HTTP client in C that basically just sends a HTTP GET and reads the response from ths server. Now I want to separate the headers from the body. The question is, is it possible to read from the socket byte-by-byte:
while(recv(sockfd, buffer, 1, 0))
{
// do whatever with buffer[0]
}
or is it so that: once the server wrote to the socket, say, 1000 bytes, so once the client reads even 1 bytes than all this message is "wasted" and cannot be read anymore?
Because I remember that when dealing with sockets sometime in the past that was how I understood that it is working.
Yes, in TCP that is possible. TCP does not have messages, only bytes, like a file. You can send 1000 bytes and then receive 1 byte 1000 times.
In fact that is a convenient way to start out, because if you try to receive more than 1 byte, you might not get the same number of bytes you asked for, you could get any number down to 1 byte. If you only ask to receive 1 byte, then you always get exactly 1 byte (unless the connection is closed).
It is inefficient, however, because the receive function uses a certain amount of CPU time just to process the fact that you want to receive - i.e. the function call itself costs a bit of CPU time. If you ask for, say, 100000 bytes at once, then you don't have to call the receive function 100000 times to get it. It's probably fast enough for you, just not as fast as it could be.
Although it is not good practice, it isn't "wasted". Most socket implementations on OS's do use a socket buffer, ranging from 4K till 6MB. So yes you can, as long as you read it fast engough.
But still, it is saver to just copy the stuf to your own memory-managed buffer..
If I want to sniffing packet in linux without set any filters, I saw 2 options.
Use libpcap
Use raw socket myself like https://www.binarytides.com/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/
Why libpcap is better than use raw sockets myself?
Three reasons:
1) It's way easier to correctly set up.
2) It's portable, even to Windows, which uses a quite similar yet different API for sockets.
3) It's MUCH faster.
1 and 2, IMO, don't need much explanation. I'll dive into 3.
To understand why libpcap is (generally) faster, we need to understand the bottlenecks in the socket API.
The two biggest bottlenecks that libpcap tends to avoid are syscalls and copies.
How it does so is platform-specific.
I'll tell the story for Linux.
Linux, since 2.0 IIRC, implements what it calls AF_PACKET socket family, and later with it PACKET_MMAP. I don't exactly recall the benefits of the former, but the latter is critical to avoid both copying from kernel to userspace (there are still a few copies kernel-side) and syscalls.
In PACKET_MMAP you allocate a big ring buffer in userspace, and then associate it to an AF_PACKET socket. This ring buffer will contain a bit of metadata (most importantly, a marker that says if a region is ready for user processing) and the packet contents.
When a packet arrives to a relevant interface (generally one you bind your socket to), the kernel makes a copy in the ring buffer and marks the location as ready for userspace*.
If the application was waiting on the socket, it gets notified*.
So, why is this better than raw sockets? Because you can do with few or none syscalls after setting up the socket, depending on whether you want to busy-poll the buffer itself or wait with poll until a few packets are ready, and because you don't need the copy from the socket's internal RX buffer to your user buffers, since it's shared with you.
libpcap does all of that for you. And does it on Mac, *BSD, and pretty much any platform that provides you with faster capture methods.
*It's a bit more complex on version 3, where the granularity is in "blocks" instead of packets.
I have a server which needs to transfer a large amount of data (~1-2 gigs) per request. What is the recommended amount of data that each call to send should have? Does it matter?
The TCP/IP stack takes care of not sending packets larger than the PATH MTU, and you would have to work rather hard to make it send packets smaller than the MTU, in ways that wouldn't help throughput: and there is no way of dsicovering what the path PTU actually is for any given connection. So leave all consideration of the path MTU out of it.
You can and should make every send() as big as possible.
Your packet size is constraint by the Maximum Transfer Unit (MTU) of the protocol. If you send a packet bigger than the MTU then you get packet fragmentation.
You can do some math: http://www.speedguide.net/articles/mtu-what-difference-does-it-make--111
More References: http://en.wikipedia.org/wiki/Maximum_transmission_unit
But ultimately my suggestion is that if you aim for good enough and just let the os network layer do its work, unless you are programming raw sockets or passing some funky options, is pretty common that the os will have a network buffer and will try to do its best.
Considering this last option then the socket.send() is nothing else than a memory transfer from your user process memory to the kernel's private memory. The rule of thumb is to not exceed the virtual memory page size http://en.wikipedia.org/wiki/Page_(computer_memory) that is usually 4KB.
I'm having a question regarding send() on TCP sockets.
Is there a difference between:
char *text="Hello world";
char buffer[150];
for(i=0;i<10;i++)
send(fd_client, text, strlen(text) );
and
char *text="Hello world";
char buffer[150];
buffer[0]='\0';
for(i=0;i<10;i++)
strcat(buffer, text);
send(fd_client, buffer, strlen(buffer) );
Is there a difference for the receiver side using recv?
Are both going to be one TCP packet?
Even if TCP_NODELAY is set?
There's really no way to know. Depends on the implementation of TCP. If it were a UDP socket, they would definitely have different results, where you would have several packets in the first case and one in the second.
TCP is free to split up packets as it sees fit; it emulates a stream and abstracts it's packet mechanics away from the user. This is by design.
TCP is stream based protocol. If you run Send, it will put some data into OS TCP layer buffer and OS will send it periodically. But if you call Send too quick it might put few arrays into OS TCP layer before the previous one were sent. So it is like stack, it sends whatever it has and put everything in one big array.
Sending is btw done with segmentation by OS TCP layer, and there is as well Nagle's algorithm that will prevent sending small amount data before OS buffer will be big enough to satisfy one segment size.
So yes, there is difference.
TCP is stream based protocol, you can't rely on that single send will be single receive with same amount of data.
Data might merge together and you have to remember about that all the time.
Btw, based on your examples, in first case client will receive all bytes together or nothing. In meantime if sending one big segment will drop somewhere on the way then server OS will automatically resend it. Drop chance for bigger packets is higher so and resending of big segments will lead to some traffic lose. But this is based on percentage of dropped packets and might be not actual for your case at all.
In second example you might receive everything together or parts each separate or some merged. You never know and should implement you network reading that way, that you know how many bytes you expecting to receive and read just that amount of bytes. That way even if there is left some unread bytes they will be read on next "Read".
i have a client which sends data to a server with 2 consecutive send calls:
send(_sockfd,msg,150,0);
send(_sockfd,msg,150,0);
and the server is receiving when the first send call was sent (let's say i'm using select):
recv(_sockfd,buf,700,0);
note that the buffer i'm receiving is much bigger.
my question is: is there any chance that buf will contain both msgs? of do i need 2 recv() calls to get both msgs?
thank you!
TCP is a stream oriented protocol. Not message / record / chunk oriented. That is, all that is guaranteed is that if you send a stream, the bytes will get to the other side in the order you sent them. There is no provision made by RFC 793 or any other document about the number of segments / packets involved.
This is in stark contrast with UDP. As #R.. correctly said, in UDP an entire message is sent in one operation (notice the change in terminology: message). Try to send a giant message (several times larger than the MTU) with TCP ? It's okay, it will split it for you.
When running on local networks or on localhost you will certainly notice that (generally) one send == one recv. Don't assume that. There are factors that change it dramatically. Among these
Nagle
Underlying MTU
Memory usage (possibly)
Timers
Many others
Of course, not having a correspondence between an a send and a recv is a nuisance and you can't rely on UDP. That is one of the reasons for SCTP. SCTP is a really really interesting protocol and it is message-oriented.
Back to TCP, this is a common nuisance. An equally common solution is this:
Establish that all packets begin with a fixed-length sequence (say 32 bytes)
These 32 bytes contain (possibly among other things) the size of the message that follows
When you read any amount of data from the socket, add the data to a buffer specific for that connection. When 32 bytes are reached, read the length you still need to read until you get the message.
It is really important to notice how there are really no messages on the wire, only bytes. Once you understand it you will have made a giant leap towards writing network applications.
The answer depends on the socket type, but in general, yes it's possible. For TCP it's the norm. For UDP I believe it cannot happen, but I'm not an expert on network protocols/programming.
Yes, it can and often does. There is no way of matching up sends and receive calls when using TCP/IP. Your program logic should test the return values of both send and recv calls in a loop, which terminates when everything has been sent or recieved.