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

📄 24.htm

📁 unix高级编程原吗
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<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="25.htm">下一篇</a>]
<hr><p align="left"><small>发信人: fion (fion), 信区: UNP <br>

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

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

  <br>

  2.  Questions regarding both Clients and Servers (TCP/SOCK_STREAM) <br>

  <br>

2.1.  How can I tell when a socket is closed on the other end? <br>

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

  AFAIK: <br>

  If the peer calls close() or exits, without having messed with <br>

  SO_LINGER, then our calls to read() should return 0. It is less clear <br>

  what happens to write() calls in this case; I would expect EPIPE, not <br>

  on the next call, but the one after. <br>

  If the peer reboots, or sets l_onoff = 1, l_linger = 0 and then <br>

  closes, then we should get ECONNRESET (eventually) from read(), or <br>

  EPIPE from write(). <br>

  I should also point out that when write() returns EPIPE, it also <br>

  raises the SIGPIPE signal - you never see the EPIPE error unless you <br>

  handle or ignore the signal. <br>

  If the peer remains unreachable, we should get some other error. <br>

  I don't think that write() can legitimately return 0.  read() should <br>

  return 0 on receipt of a FIN from the peer, and on all following <br>

  calls. <br>

  calls. <br>

  So yes, you must expect read() to return 0. <br>

  As an example, suppose you are receiving a file down a TCP link; you <br>

  might handle the return from read() like this: <br>

  rc = read(sock,buf,sizeof(buf)); <br>

  if (rc > 0) <br>

  { <br>

      write(file,buf,rc); <br>

      /* error checking on file omitted */ <br>

  } <br>

  else if (rc == 0) <br>

  { <br>

      close(file); <br>

      close(sock); <br>

      /* file received successfully */ <br>

  } <br>

  else /* rc < 0 */ <br>

  { <br>

      /* close file and delete it, since data is not complete <br>

         report error, or whatever */ <br>

  } <br>

  <br>

2.2.  What's with the second parameter in bind()? <br>



  The man page shows it as "struct sockaddr *my_addr".  The sockaddr <br>

  struct though is just a place holder for the structure it really <br>

  wants.  You have to pass different structures depending on what kind <br>

  of socket you have.  For an AF_INET socket, you need the sockaddr_in <br>

  structure.  It has three fields of interest: <br>

     sin_family <br>

        Set this to AF_INET. <br>

     sin_port <br>

        The network byte-ordered 16 bit port number <br>

     sin_addr <br>

        The host's ip number.  This is a struct in_addr, which contains <br>

        only one field, s_addr which is a u_long. <br>

  <br>

2.3.  How do I get the port number for a given service? <br>

  Use the getservbyname() routine.  This will return a pointer to a <br>

  servent structure.  You are interested in the s_port field, which <br>

  contains the port number, with correct byte ordering (so you don't <br>

  need to call htons() on it).  Here is a sample routine: <br>

  /* Take a service name, and a service type, and return a port number.  If <br>

the <br>

     service name is not found, it tries it as a decimal number.  The number <br>

  <br>

  <br>

     returned is byte ordered for the network. */ <br>

  int atoport(char *service, char *proto) { <br>

    int port; <br>

    long int lport; <br>

    struct servent *serv; <br>

    char *errpos; <br>

    /* First try to read it from /etc/services */ <br>

    serv = getservbyname(service, proto); <br>

    if (serv != NULL) <br>

      port = serv->s_port; <br>

    else { /* Not in services, maybe a number? */ <br>

      lport = strtol(service,&errpos,0); <br>

      if ( (errpos[0] != 0) || (lport < 1) || (lport > 5000) ) <br>

        return -1; /* Invalid port address */ <br>

      port = htons(lport); <br>

    } <br>

    return port; <br>

  } <br>

  <br>

2.4.  If bind() fails, what should I do with the socket descriptor? <br>

  If you are exiting, I have been assured by Andrew that all unixes will <br>

  close open file descriptors on exit.  If you are not exiting though, <br>



  you can just close it with a regular close() call. <br>

  <br>

2.5.  How do I properly close a socket? <br>

  This question is usually asked by people who try close(), because they <br>

  have seen that that is what they are supposed to do, and then run <br>

  netstat and see that their socket is still active.  Yes, close() is <br>

  the correct method.  To read about the TIME_WAIT state, and why it is <br>

  important, refer to ``2.7 Please explain the TIME_WAIT state.''. <br>

  <br>

2.6.  When should I use shutdown()? <br>

  From Michael Hunter (mphunter@qnx.com): <br>

  shutdown() is useful for deliniating when you are done providing a <br>

  request to a server using TCP.  A typical use is to send a request to <br>

  a server followed by a shutdown().  The server will read your request <br>

  followed by an EOF (read of 0 on most unix implementations).  This <br>

  tells the server that it has your full request.  You then go read <br>

  blocked on the socket.  The server will process your request and send <br>

  the necessary data back to you followed by a close.  When you have <br>

  finished reading all of the response to your request you will read an <br>

  EOF thus signifying that you have the whole response.  It should be <br>

  noted the TTCP (TCP for Transactions -- see R. Steven's home page) <br>

  provides for a better method of tcp transaction management. <br>



  S.Degtyarev (deg@sunsr.inp.nsk.su) wrote a nice in-depth message to me <br>

  about this.  He shows a practical example of using shutdown() to aid <br>

  in synchronization of client processes when one is the "reader" <br>

  process, and the other is the "writer" process.  A portion of his <br>

  message follows: <br>

  Sockets are very similar to pipes in the way they are used for data <br>

  transfer and client/server transactions, but not like pipes they are <br>

  bidirectional.  Programs that use sockets often fork() and each <br>

  process inherits the socket descriptor.  In pipe based programs it is <br>

  strictly recommended to close all the pipe ends that are not used to <br>

  convert the pipe line to one-directional data stream to avoid data <br>

  losses and deadlocks.  With the socket there is no way to allow one <br>

  process only to send data and the other only to receive so you should <br>

  always keep in mind the consequences. <br>

  Generally the difference between close() and shutdown() is: close() <br>

  closes the socket id for the process but the connection is still <br>

  opened if another process shares this socket id.  The connection stays <br>

  opened both for read and write, and sometimes this is very important. <br>

  shutdown() breaks the connection for all processes sharing the socket <br>

  id.  Those who try to read will detect EOF, and those who try to write <br>

  will reseive SIGPIPE, possibly delayed while the kernel socket buffer <br>

  will be filled.  Additionally, shutdown() has a second argument which <br>



  denotes how to close the connection: 0 means to disable further <br>

  reading, 1 to disable writing and 2 disables both. <br>

  The quick example below is a fragment of a very simple client process. <br>

  After establishing the connection with the server it forks.  Then <br>

  child sends the keyboard input to the server until EOF is received and <br>

  the parent receives answers from the server. <br>

       /* <br>

        *      Sample client fragment, <br>

        *      variables declarations and error handling are omitted <br>

        */ <br>

               s=connect(...); <br>

               if( fork() ){   /*      The child, it copies its stdin to <br>

                                               the socket              */ <br>

                       while( gets(buffer) >0) <br>

                               write(s,buf,strlen(buffer)); <br>

                       close(s); <br>

                       exit(0); <br>

                       } <br>

               else {          /* The parent, it receives answers  */ <br>

                       while( (l=read(s,buffer,sizeof(buffer)){ <br>

                               do_something(l,buffer); <br>

                       /* Connection break from the server is assumed  */ <br>



                       /* ATTENTION: deadlock here                     */ <br>

                       wait(0); /* Wait for the child to exit          */ <br>

                       exit(0); <br>

                       } <br>

  What do we expect? The child detects an EOF from its stdin, it closes <br>

  the socket (assuming connection break) and exits.  The server in its <br>

  turn detects EOF, closes connection and exits.  The parent detects <br>

  EOF, makes the wait() system call and exits.  What do we see instead? <br>

  The socket instance in the parent process is still opened for writing <br>

  and reading, though the parent never writes.  The server never detects <br>

  EOF and waits for more data from the client forever.  The parent never <br>

  sees the connection is closed and hangs forever and the server hangs <br>

  too.  Unexpected deadlock!  ( any deadlock is unexpected though :-) <br>

  You should change the client fragment as follows: <br>

                       if( fork() ) {  /* The child                    */ <br>

                               while( gets(buffer) } <br>

                                       write(s,buffer,strlen(buffer)); <br>

                                       shutdown(s,1); /* Break the connectio <br>

n <br>

               for writing, The server will detect EOF now. Note: reading fr <br>

om <br>

               the socket is still allowed. The server may send some more da <br>



ta <br>

               after receiving EOF, why not? */ <br>

                               exit(0); <br>

                               } <br>

  I hope this rough example explains the troubles you can have with <br>

  client/server syncronization.  Generally you should always remember <br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -