?? syscalls.html
字號:
></DIV><DIVCLASS="sect2"><H2CLASS="sect2"><ANAME="closedown">4.8. <TTCLASS="function">close()</TT> and<TTCLASS="function">shutdown()</TT>--Get outta my face!</A></H2><P>Whew! You've been <TTCLASS="function">send()</TT>ing and<TTCLASS="function">recv()</TT>ing data all day long, and you've had it.You're ready to close the connection on your socket descriptor. This iseasy. You can just use the regular Unix file descriptor<TTCLASS="function">close()</TT> function:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> close(sockfd); </PRE></TD></TR></TABLE><P>This will prevent any more reads and writes to the socket. Anyoneattempting to read or write the socket on the remote end will receive anerror.</P><P>Just in case you want a little more control over how the socketcloses, you can use the <TTCLASS="function">shutdown()</TT> function. Itallows you to cut off communication in a certain direction, or both ways(just like <TTCLASS="function">close()</TT> does.) Synopsis:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> int shutdown(int sockfd, int how); </PRE></TD></TR></TABLE><P><TTCLASS="parameter"><I>sockfd</I></TT> is the socket file descriptor youwant to shutdown, and <TTCLASS="parameter"><I>how</I></TT> is one of thefollowing:</P><P></P><UL><LI><P><TTCLASS="constant">0</TT> -- Further receives aredisallowed</P></LI><LI><P><TTCLASS="constant">1</TT> -- Further sends aredisallowed</P></LI><LI><P><TTCLASS="constant">2</TT> -- Further sends and receives aredisallowed (like <TTCLASS="function">close()</TT>)</P></LI></UL><P><TTCLASS="function">shutdown()</TT> returns <TTCLASS="constant">0</TT> onsuccess, and <TTCLASS="constant">-1</TT> on error (with<TTCLASS="parameter"><I>errno</I></TT> set accordingly.)</P><P>If you deign to use <TTCLASS="function">shutdown()</TT> on unconnecteddatagram sockets, it will simply make the socket unavailable for further<TTCLASS="function">send()</TT> and <TTCLASS="function">recv()</TT> calls(remember that you can use these if you <TTCLASS="function">connect()</TT>your datagram socket.)</P><P>It's important to note that <TTCLASS="function">shutdown()</TT>doesn't actually close the file descriptor--it just changes itsusability. To free a socket descriptor, you need to use<TTCLASS="function">close()</TT>.</P><P>Nothing to it.</P></DIV><DIVCLASS="sect2"><H2CLASS="sect2"><ANAME="getpeername">4.9. <TTCLASS="function">getpeername()</TT>--Who are you?</A></H2><P>This function is so easy.</P><P>It's so easy, I almost didn't give it it's own section. But hereit is anyway.</P><P>The function <TTCLASS="function">getpeername()</TT> will tell you who is at the other endof a connected stream socket. The synopsis:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> #include <sys/socket.h> int getpeername(int sockfd, struct sockaddr *addr, int *addrlen); </PRE></TD></TR></TABLE><P><TTCLASS="parameter"><I>sockfd</I></TT> is the descriptor of the connectedstream socket, <TTCLASS="parameter"><I>addr</I></TT> is a pointer to a<TTCLASS="type">struct sockaddr</TT> (or a <TTCLASS="type">struct sockaddr_in</TT>) thatwill hold the information about the other side of the connection, and<TTCLASS="parameter"><I>addrlen</I></TT> is a pointer to an <TTCLASS="type">int</TT>, thatshould be initialized to <TTCLASS="computeroutput">sizeof(structsockaddr)</TT>.</P><P>The function returns <TTCLASS="constant">-1</TT> on error and sets<TTCLASS="parameter"><I>errno</I></TT> accordingly.</P><P>Once you have their address, you can use<TTCLASS="function">inet_ntoa()</TT> or <TTCLASS="function">gethostbyaddr()</TT>to print or get more information. No, you can't get their login name.(Ok, ok. If the other computer is running an ident daemon, this ispossible. This, however, is beyond the scope of this document. Checkout <AHREF="http://www.rfc-editor.org/rfc/rfc1413.txt"TARGET="_top">RFC-1413</A> for moreinfo.)</P></DIV><DIVCLASS="sect2"><H2CLASS="sect2"><ANAME="gethostname">4.10. <TTCLASS="function">gethostname()</TT>--Who am I?</A></H2><P>Even easier than <TTCLASS="function">getpeername()</TT> is thefunction <TTCLASS="function">gethostname()</TT>. It returns the name of thecomputer that your program is running on. The name can then be used by<TTCLASS="function">gethostbyname()</TT>, below, to determine the IP addressof your local machine.</P><P>What could be more fun? I could think of a few things, but theydon't pertain to socket programming. Anyway, here's thebreakdown:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> #include <unistd.h> int gethostname(char *hostname, size_t size); </PRE></TD></TR></TABLE><P>The arguments are simple: <TTCLASS="parameter"><I>hostname</I></TT> is apointer to an array of chars that will contain the hostname upon thefunction's return, and <TTCLASS="parameter"><I>size</I></TT> is the length inbytes of the <TTCLASS="parameter"><I>hostname</I></TT> array.</P><P>The function returns <TTCLASS="constant">0</TT> on successfulcompletion, and <TTCLASS="constant">-1</TT> on error, setting<TTCLASS="parameter"><I>errno</I></TT> as usual.</P></DIV><DIVCLASS="sect2"><H2CLASS="sect2"><ANAME="dns">4.11. DNS--You say "whitehouse.gov", I say "198.137.240.92"</A></H2><P>In case you don't know what DNS is, it stands for "Domain NameService". In a nutshell, you tell it what the human-readable address isfor a site, and it'll give you the IP address (so you can use it with<TTCLASS="function">bind()</TT>, <TTCLASS="function">connect()</TT>,<TTCLASS="function">sendto()</TT>, or whatever you need it for.) This way,when someone enters:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="screen"> <TTCLASS="prompt">$</TT> <BCLASS="command">telnet whitehouse.gov</B></PRE></TD></TR></TABLE><P><BCLASS="command">telnet</B> can find out that it needs to<TTCLASS="function">connect()</TT> to "198.137.240.92".</P><P>But how does it work? You'll be using the function<TTCLASS="function">gethostbyname()</TT>:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> #include <netdb.h> struct hostent *gethostbyname(const char *name); </PRE></TD></TR></TABLE><P>As you see, it returns a pointer to a <TTCLASS="type">struct hostent</TT>,the layout of which is as follows:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; }; #define h_addr h_addr_list[0] </PRE></TD></TR></TABLE><P>And here are the descriptions of the fields in the <TTCLASS="type">structhostent</TT>:</P><P></P><UL><LI><P><TTCLASS="parameter"><I>h_name</I></TT> -- Official name of thehost.</P></LI><LI><P><TTCLASS="parameter"><I>h_aliases</I></TT> -- A NULL-terminatedarray of alternate names for the host.</P></LI><LI><P><TTCLASS="parameter"><I>h_addrtype</I></TT> -- The type of addressbeing returned; usually<TTCLASS="parameter"><I>AF_INET</I></TT>.</P></LI><LI><P><TTCLASS="parameter"><I>h_length</I></TT> -- The length of theaddress in bytes.</P></LI><LI><P><TTCLASS="parameter"><I>h_addr_list</I></TT> -- A zero-terminatedarray of network addresses for the host. Host addresses are in NetworkByte Order.</P></LI><LI><P><TTCLASS="parameter"><I>h_addr</I></TT> -- The first address in<TTCLASS="parameter"><I>h_addr_list</I></TT>.</P></LI></UL><P><TTCLASS="function">gethostbyname()</TT> returns a pointer to thefilled <TTCLASS="type">struct hostent</TT>, or NULL on error. (But<TTCLASS="parameter"><I>errno</I></TT> is <EM>not</EM>set--<EM><TTCLASS="parameter"><I>h_errno</I></TT></EM> is set instead.See <TTCLASS="function">herror()</TT>, below.)</P><P>But how is it used? Sometimes (as we find from reading computermanuals), just spewing the information at the reader is not enough.This function is certainly easier to use than it looks.</P><P><AHREF="http://www.ecst.csuchico.edu/~beej/guide/net/examples/getip.c"TARGET="_top">Here's an exampleprogram</A>:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="programlisting"> /* ** getip.c -- a hostname lookup demo */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { struct hostent *h; if (argc != 2) { // error check the command line fprintf(stderr,"usage: getip address\n"); exit(1); } if ((h=gethostbyname(argv[1])) == NULL) { // get the host info herror("gethostbyname"); exit(1); } printf("Host name : %s\n", h->h_name); printf("IP Address : %s\n", inet_ntoa(*((struct in_addr *)h->h_addr))); return 0; } </PRE></TD></TR></TABLE><P>With <TTCLASS="function">gethostbyname()</TT>, you can't use<TTCLASS="function">perror()</TT> to print error message (since<TTCLASS="parameter"><I>errno</I></TT> is not used). Instead, call<TTCLASS="function">herror()</TT>.</P><P>It's pretty straightforward. You simply pass the string thatcontains the machine name ("whitehouse.gov") to<TTCLASS="function">gethostbyname()</TT>, and then grab the information outof the returned <TTCLASS="type">struct hostent</TT>.</P><P>The only possible weirdness might be in the printing of the IPaddress, above. <TTCLASS="parameter"><I>h->h_addr</I></TT> is a<TTCLASS="type">char*</TT>, but <TTCLASS="function">inet_ntoa()</TT> wants a<TTCLASS="type">struct in_addr</TT> passed to it. So I cast<TTCLASS="parameter"><I>h->h_addr</I></TT> to a <TTCLASS="type">struct in_addr*</TT>,then dereference it to get at the data.</P></DIV></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="structs.html">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="clientserver.html">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><TTCLASS="type">struct</TT>s and Data Handling</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"> </TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Client-Server Background</TD></TR></TABLE></DIV></BODY></HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -