⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 25.htm

📁 unix高级编程原吗
💻 HTM
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>123</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center">               ● UNIX网络编程                       (BM: clown)                </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p   align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="16.htm">上一层</a>][<a href="26.htm">下一篇</a>]
<hr><p align="left"><small>发信人: fion (fion), 信区: UNP <br>

标  题: unix socket faq (4) <br>

发信站: UNIX编程 (2001年07月07日09:44:28 星期六), 站内信件 <br>

  <br>

 3.  Writing Client Applications (TCP/SOCK_STREAM) <br>

  <br>

3.1.  How do I convert a string into an internet address? <br>

  If you are reading a host's address from the command line, you may not <br>

  know if you have an aaa.bbb.ccc.ddd style address, or a <br>

  host.domain.com style address.  What I do with these, is first try to <br>

  use it as a aaa.bbb.ccc.ddd type address, and if that fails, then do a <br>

  name lookup on it.  Here is an example: <br>

       /* Converts ascii text to in_addr struct.  NULL is returned if the <br>

          address can not be found. */ <br>

       struct in_addr *atoaddr(char *address) { <br>

         struct hostent *host; <br>

         static struct in_addr saddr; <br>

         /* First try it as aaa.bbb.ccc.ddd. */ <br>

         saddr.s_addr = inet_addr(address); <br>

         if (saddr.s_addr != -1) { <br>

           return &saddr; <br>

         } <br>

         host = gethostbyname(address); <br>



         if (host != NULL) { <br>

           return (struct in_addr *) *host->h_addr_list; <br>

         } <br>

         return NULL; <br>

       } <br>

  <br>

3.2.  How can my client work through a firewall/proxy server? <br>

  If you are running through separate proxies for each service, you <br>

  shouldn't need to do anything.  If you are working through sockd, you <br>

  will need to "socksify" your application.  Details for doing this can <br>

  be found in the package itself, which is available at: <br>

       ftp://ftp.net.com/socks.cstc/socks.cstc.4.2.tar.gz <br>

  you can get the socks faq at: <br>

       ftp://coast.cs.purdue.edu/pub/tools/unix/socks/FAQ <br>

  <br>

3.3.  Why does connect() succeed even before my server did an <br>

  accept()? <br>

  From Andrew Gierth (andrew@erlenstar.demon.co.uk): <br>

  Once you have done a listen() call on your socket, the kernel is <br>

  primed to accept connections on it. The usual UNIX implementation of <br>

  this works by immediately completing the SYN handshake for any <br>

  incoming valid SYN segments (connection attempts), creating the socket <br>



  for the new connection, and keeping this new socket on an internal <br>

  queue ready for the accept() call. So the socket is fully open before <br>

  the accept is done. <br>

  The other factor in this is the 'backlog' parameter for listen(); that <br>

  defines how many of these completed connections can be queued at one <br>

  time.  If the specified number is exceeded, then new incoming connects <br>

  are simply ignored (which causes them to be retried). <br>

  <br>

3.4.  Why do I sometimes lose a server's address when using more than <br>

  one server? <br>

  From Andrew Gierth (andrew@erlenstar.demon.co.uk): <br>

  Take a careful look at struct hostent. Notice that almost everything <br>

  in it is a pointer? All these pointers will refer to statically <br>

  allocated data. <br>

  For example, if you do: <br>

           struct hostent *host = gethostbyname(hostname); <br>

  then (as you should know) a subsequent call to gethostbyname() will <br>

  overwrite the structure pointed to by 'host'. <br>

  But if you do: <br>

           struct hostent myhost; <br>

           struct hostent *hostptr = gethostbyname(hostname); <br>

           if (hostptr) myhost = *host; <br>



  to make a copy of the hostent before it gets overwritten, then it <br>

  still gets clobbered by a subsequent call to gethostbyname(), since <br>

  although myhost won't get overwritten, all the data it is pointing to <br>

  will be. <br>

  You can get round this by doing a proper 'deep copy' of the hostent <br>

  structure, but this is tedious. My recommendation would be to extract <br>

  the needed fields of the hostent and store them in your own way. <br>

  Robin Paterson (etmrpat@etm.ericsson.se) has added: <br>

  It might be nice if you mention MT safe libraries provide <br>

  complimentary functions for multithreaded programming.  On the solaris <br>

  machine I'm typing at, we have gethostbyname and gethostbyname_r (_r <br>

  for reentrant).  The main difference is, you provide the storage for <br>

  the hostent struct so you always have a local copy and not just a <br>

  pointer to the static copy. <br>

  <br>

3.5.  How can I set the timeout for the connect() system call? <br>

  From Richard Stevens (rstevens@noao.edu): <br>

  Normally you cannot change this.  Solaris does let you do this, on a <br>

  per-kernel basis with the ndd tcp_ip_abort_cinterval parameter. <br>

  The easiest way to shorten the connect time is with an alarm() around <br>

  the call to connect().  A harder way is to use select(), after setting <br>

  the socket nonblocking.  Also notice that you can only shorten the <br>



  connect time, there's normally no way to lengthen it. <br>

  From Andrew Gierth (andrew@erlenstar.demon.co.uk): <br>

  First, create the socket and put it into non-blocking mode, then call <br>

  connect(). There are three possibilities: <br>

  o  connect succeeds: the connection has been successfully made (this <br>

     usually only happens when connecting to the same machine) <br>

  o  connect fails: obvious <br>

  o  connect returns -1/EINPROGRESS. The connection attempt has begun, <br>

     but not yet completed. <br>

  If the connection succeeds: <br>

  o  the socket will select() as writable (and will also select as <br>

     readable if data arrives) <br>

  If the connection fails: <br>

  o  the socket will select as readable *and* writable, but either a <br>

     read or write will return the error code from the connection <br>

     attempt. Also, you can use getsockopt(SO_ERROR) to get the error <br>

     status - but be careful; some systems return the error code in the <br>

     result parameter of getsockopt, but others (incorrectly) cause the <br>

     getsockopt call *itself* to fail with the stored value as the <br>

     error. <br>

  <br>

3.6.  system choose one for me on the connect() call?  Should I bind() <br>



  a port number in my client program, or let the <br>

  From Andrew Gierth (andrew@erlenstar.demon.co.uk): <br>

  ** Let the system choose your client's port number ** <br>

  The exception to this, is if the server has been written to be picky <br>

  about what client ports it will allow connections from. Rlogind and <br>

  rshd are the classic examples. This is usually part of a Unix-specific <br>

  (and rather weak) authentication scheme; the intent is that the server <br>

  allows connections only from processes with root privilege. (The <br>

  weakness in the scheme is that many O/Ss (e.g. MS-DOS) allow anyone to <br>

  bind any port.) <br>

  The rresvport() routine exists to help out clients that are using this <br>

  scheme. It basically does the equivalent of socket() + bind(), <br>

  choosing a port number in the range 512..1023. <br>

  If the server is not fussy about the client's port number, then don't <br>

  try and assign it yourself in the client, just let connect() pick it <br>

  for you. <br>

  If, in a client, you use the naive scheme of starting at a fixed port <br>

  number and calling bind() on consecutive values until it works, then <br>

  you buy yourself a whole lot of trouble: <br>

  The problem is if the server end of your connection does an active <br>

  close.  (E.G. client sends 'QUIT' command to server, server responds <br>

  by closing the connection). That leaves the client end of the <br>



  connection in CLOSED state, and the server end in TIME_WAIT state. So <br>

  after the client exits, there is no trace of the connection on the <br>

  client end. <br>

  Now run the client again. It will pick the same port number, since as <br>

  far as it can see, it's free. But as soon as it calls connect(), the <br>

  server finds that you are trying to duplicate an existing connection <br>

  (although one in TIME_WAIT). It is perfectly entitled to refuse to do <br>

  this, so you get, I suspect, ECONNREFUSED from connect(). (Some <br>

  systems may sometimes allow the connection anyway, but you can't rely <br>

  on it.) <br>

  This problem is especially dangerous because it doesn't show up unless <br>

  the client and server are on different machines. (If they are the same <br>

  machine, then the client won't pick the same port number as before). <br>

  So you can get bitten well into the development cycle (if you do what <br>

  I suspect most people do, and test client & server on the same box <br>

  initially). <br>

  Even if your protocol has the client closing first, there are still <br>

  ways to produce this problem (e.g. kill the server). <br>

  <br>

3.7.  Why do I get "connection refused" when the server isn't running? <br>

  The connect() call will only block while it is waiting to establish a <br>

  connection.  When there is no server waiting at the other end, it gets <br>



  notified that the connection can not be established, and gives up with <br>

  the error message you see.  This is a good thing, since if it were not <br>

  the case clients might wait for ever for a service which just doesn't <br>

  exist.  Users would think that they were only waiting for the <br>

  connection to be established, and then after a while give up, <br>

  muttering something about crummy software under their breath. <br>

  <br>

3.8.  over the socket ? Is there a way to have a dynamic buffer ? <br>

  What does one do when one does not know how much information is com- <br>

  ming <br>

  This question asked by Niranjan Perera (perera@mindspring.com). <br>

  When the size of the incoming data is unknown, you can either make the <br>

  size of the buffer as big as the largest possible (or likely) buffer, <br>

  or you can re-size the buffer on the fly during your read.  When you <br>

  malloc() a large buffer, most (if not all) varients of unix will only <br>

  allocate address space, but not physical pages of ram.  As more and <br>

  more of the buffer is used, the kernel allocates physical memory. <br>

  This means that malloc'ing a large buffer will not waste resources <br>

  unless that memory is used, and so it is perfectly acceptable to ask <br>

  for a meg of ram when you expect only a few K. <br>

  On the other hand, a more elegant solution that does not depend on the <br>

  inner workings of the kernel is to use realloc() to expand the buffer <br>



  as required in say 4K chunks (since 4K is the size of a page of ram on <br>

  most systems).  I may add something like this to sockhelp.c in the <br>

  example code one day. <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="26.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 + -