📄 24.htm
字号:
structure apart on one side, and putting it back together on the <br>
other. If you need to send floats, you may have a lot of work ahead <br>
of you. You should read RFC 1014 which is about portable ways of <br>
getting data from one machine to another (thanks to Andrew Gabriel for <br>
pointing this out). <br>
<br>
2.16. How do I use TCP_NODELAY? <br>
First off, be sure you really want to use it in the first place. It <br>
will disable the Nagle algorithm (see ``2.11 How can I force a socket <br>
to send the data in its buffer?''), which will cause network traffic <br>
to increase, with smaller than needed packets wasting bandwidth. <br>
Also, from what I have been able to tell, the speed increase is very <br>
small, so you should probably do it without TCP_NODELAY first, and <br>
only turn it on if there is a problem. <br>
Here is a code example, with a warning about using it from Andrew <br>
Gierth: <br>
int flag = 1; <br>
int result = setsockopt(sock, /* socket affected */ <br>
IPPROTO_TCP, /* set option at TCP level <br>
*/ <br>
*/ <br>
TCP_NODELAY, /* name of option */ <br>
(char *) &flag, /* the cast is historical <br>
cruft */ <br>
sizeof(int)); /* length of option value <br>
*/ <br>
if (result < 0) <br>
... handle the error ... <br>
TCP_NODELAY is for a specific purpose; to disable the Nagle buffering <br>
algorithm. It should only be set for applications that send frequent <br>
small bursts of information without getting an immediate response, <br>
where timely delivery of data is required (the canonical example is <br>
mouse movements). <br>
<br>
2.17. What exactly does the Nagle algorithm do? <br>
It groups together as much data as it can between ACK's from the other <br>
end of the connection. I found this really confusing until Andrew <br>
Gierth (andrew@erlenstar.demon.co.uk) drew the following diagram, and <br>
explained: <br>
This diagram is not intended to be complete, just to illustrate the <br>
point better... <br>
Case 1: client writes 1 byte per write() call. The program on host B <br>
is tcpserver.c from the FAQ examples. <br>
CLIENT SERVER <br>
APP TCP TCP APP <br>
[connection setup omitted] <br>
"h" ---------> [1 byte] <br>
------------------> <br>
-----------> "h" <br>
[ack delayed] <br>
"e" ---------> [Nagle alg. . <br>
now in effect] . <br>
"l" ---------> [ditto] . <br>
"l" ---------> [ditto] . <br>
"o" ---------> [ditto] . <br>
"\n"---------> [ditto] . <br>
. <br>
. <br>
[ack 1 byte] <br>
<------------------ <br>
[send queued <br>
data] <br>
[5 bytes] <br>
------------------> <br>
------------> "ello\n" <br>
<------------ "HELLO\n" <br>
[6 bytes, ack 5 bytes] <br>
<------------------ <br>
"HELLO\n" <---- <br>
[ack delayed] <br>
. <br>
. <br>
. [ack 6 bytes] <br>
------------------> <br>
Total segments: 5. (If TCP_NODELAY was set, could have been up to 10.) <br>
Time for response: 2*RTT, plus ack delay. <br>
Case 2: client writes all data with one write() call. <br>
CLIENT SERVER <br>
APP TCP TCP APP <br>
[connection setup omitted] <br>
"hello\n" ---> [6 bytes] <br>
------------------> <br>
------------> "hello\n" <br>
<------------ "HELLO\n" <br>
[6 bytes, ack 6 bytes] <br>
<------------------ <br>
"HELLO\n" <---- <br>
[ack delayed] <br>
. <br>
. <br>
. [ack 6 bytes] <br>
------------------> <br>
Total segments: 3. <br>
Time for response = RTT (therefore minimum possible). <br>
Hope this makes things a bit clearer... <br>
Note that in case 2, you don't want the implementation to gratuitously <br>
delay sending the data, since that would add straight onto the <br>
response time. <br>
<br>
2.18. What is the difference between read() and recv()? <br>
From Andrew Gierth (andrew@erlenstar.demon.co.uk): <br>
read() is equivalent to recv() with a flags parameter of 0. Other <br>
values for the flags parameter change the behaviour of recv(). <br>
Similarly, write() is equivalent to send() with flags == 0. <br>
It is unlikely that send()/recv() would be dropped; perhaps someone <br>
with a copy of the POSIX drafts for socket calls can check... <br>
Portability note: non-unix systems may not allow read()/write() on <br>
sockets, but recv()/send() are usually ok. This is true on Windows and <br>
OS/2, for example. <br>
<br>
2.19. I see that send()/write() can generate SIGPIPE. Is there any <br>
advantage to handling the signal, rather than just ignoring it and <br>
checking for the EPIPE error? Are there any useful parameters passed <br>
to the signal catching function? <br>
From Andrew Gierth (andrew@erlenstar.demon.co.uk): <br>
In general, the only parameter passed to a signal handler is the <br>
signal number that caused it to be invoked. Some systems have <br>
optional additional parameters, but they are no use to you in this <br>
case. <br>
My advice is to just ignore SIGPIPE as you suggest. That's what I do <br>
in just about all of my socket code; errno values are easier to handle <br>
than signals (in fact, the first revision of the FAQ failed to mention <br>
SIGPIPE in that context; I'd got so used to ignoring it...) <br>
There is one situation where you should not ignore SIGPIPE; if you are <br>
going to exec() another program with stdout redirected to a socket. In <br>
this case it is probably wise to set SIGPIPE to SIG_DFL before doing <br>
the exec(). <br>
<br>
2.20. After the chroot(), calls to socket() are failing. Why? <br>
From Andrew Gierth (andrew@erlenstar.demon.co.uk): <br>
On systems where sockets are implemented on top of Streams (e.g. all <br>
SysV-based systems, presumably including Solaris), the socket() <br>
function will actually be opening certain special files in /dev. You <br>
will need to create a /dev directory under your fake root and populate <br>
it with the required device nodes (only). <br>
Your system documentation may or may not specify exactly which device <br>
nodes are required; I can't help you there (sorry). (Editors note: <br>
Adrian Hall (adrian@waltham.harvard.net) suggested checking the man <br>
page for ftpd, which should list the files you need to copy and <br>
devices you need to create in the chroot'd environment.) <br>
A less-obvious issue with chroot() is if you call syslog(), as many <br>
daemons do; syslog() opens (depending on the system) either a UDP <br>
socket, a FIFO or a Unix-domain socket. So if you use it after a <br>
chroot() call, make sure that you call openlog() *before* the chroot. <br>
<br>
2.21. Why do I keep getting EINTR from the socket calls? <br>
This isn't really so much an error as an exit condition. It means <br>
that the call was interrupted by a signal. Any call that might block <br>
should be wrapped in a loop that checkes for EINTR, as is done in the <br>
example code (See ``6. Sample Source Code''). <br>
<br>
2.22. When will my application receive SIGPIPE? <br>
From Richard Stevens (rstevens@noao.edu): <br>
Very simple: with TCP you get SIGPIPE if your end of the connection <br>
has received an RST from the other end. What this also means is that <br>
if you were using select instead of write, the select would have <br>
indicated the socket as being readable, since the RST is there for you <br>
to read (read will return an error with errno set to ECONNRESET). <br>
Basically an RST is TCP's response to some packet that it doesn't <br>
expect and has no other way of dealing with. A common case is when <br>
the peer closes the connection (sending you a FIN) but you ignore it <br>
because you're writing and not reading. (You should be using select.) <br>
So you write to a connection that has been closed by the other end and <br>
the oether end's TCP responds with an RST. <br>
<br>
2.23. What are socket exceptions? What is out-of-band data? <br>
Unlike exceptions in C++, socket exceptions do not indicate that an <br>
error has occured. Socket exceptions usually refer to the <br>
notification that out-of-band data has arrived. Out-of-band data <br>
(called "urgent data" in TCP) looks to the application like a separate <br>
stream of data from the main data stream. This can be useful for <br>
separating two different kinds of data. Note that just because it is <br>
called "urgent data" does not mean that it will be delivered any <br>
faster, or with higher priorety than data in the in-band data stream. <br>
Also beware that unlike the main data stream, the out-of-bound data <br>
may be lost if your application can't keep up with it. <br>
<br>
2.24. running on? How can I find the full hostname (FQDN) of the <br>
system I'm <br>
From Richard Stevens (rstevens@noao.edu): <br>
Some systems set the hostname to the FQDN and others set it to just <br>
the unqualified host name. I know the current BIND FAQ recommends the <br>
FQDN, but most Solaris systems, for example, tend to use only the <br>
unqualified host name. <br>
Regardless, the way around this is to first get the host's name <br>
(perhaps an FQDN, perhaps unaualified). Most systems support the <br>
Posix way to do this using uname(), but older BSD systems only provide <br>
gethostname(). Call gethostbyname() to find your IP address. Then <br>
take the IP address and call gethostbyaddr(). The h_name member of <br>
the hostent{} should then be your FQDN. <br>
-- <br>
※ 来源:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 211.69.197.132] <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="16.htm">上一层</a>][<a href="25.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -