﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-牵着老婆满街逛-文章分类-网络编程</title><link>http://www.cppblog.com/tx7do/category/1513.html</link><description>严以律己,宽以待人. 三思而后行.&lt;/br&gt;
GMail/GTalk: yanglinbo#google.com;&lt;/br&gt;
MSN/Email: tx7do#yahoo.com.cn;&lt;/br&gt;
QQ: 3 0 3 3 9 6 9 2 0 .</description><language>zh-cn</language><lastBuildDate>Thu, 10 Jun 2010 17:03:12 GMT</lastBuildDate><pubDate>Thu, 10 Jun 2010 17:03:12 GMT</pubDate><ttl>60</ttl><item><title>  Linux Socket编程实例(一个Hello World程序) </title><link>http://www.cppblog.com/tx7do/articles/5966.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:49:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5966.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5966.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5966.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5966.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5966.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在Linux下写了个小的socket程序，分为客户端和服务器端,服务端开一个端口(2000),做为一个daemon,等待客户的连接请求.一旦有客户连接,服务器端打印出客户端的IP地址和端口,并且向服务器端发送欢迎信息和时间.下面是服务端的代码(tcpserver.c).由于这只是个简单的程序，所以只用了单线程实现!/**//*&nbsp;*&nbsp;*&nbsp;Tcp&nbsp;Serve...&nbsp;&nbsp;<a href='http://www.cppblog.com/tx7do/articles/5966.html'>阅读全文</a><img src ="http://www.cppblog.com/tx7do/aggbug/5966.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:49 <a href="http://www.cppblog.com/tx7do/articles/5966.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux 下Socket编程基础 </title><link>http://www.cppblog.com/tx7do/articles/5962.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:40:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5962.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5962.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5962.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5962.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5962.html</trackback:ping><description><![CDATA[<table border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td>作者： 东北大学秦皇岛分校软件中心技术研发部 敬茂华</td>
        </tr>
    </tbody>
</table>
<br>1、&nbsp;引言<br>Linux的兴起可以说是Internet创造的一个奇迹。Linux作为一个完全开放其原代码的免费的自由软件，兼容了各种UNIX标准（如POSIX、UNIX&nbsp;System&nbsp;V&nbsp;和&nbsp;BSD&nbsp;UNIX&nbsp;等）的多用户、多任务的具有复杂内核的操作系统。在中国，随着Internet的普及，一批主要以高等院校的学生和ISP的技术人员组成的Linux爱好者队伍已经蓬勃成长起来。越来越多的编程爱好者也逐渐酷爱上这个优秀的自由软件。本文介绍了Linux下Socket的基本概念和函数调用。<br><br>2、&nbsp;什么是Socket<br>Socket（套接字）是通过标准的UNIX文件描述符和其它程序通讯的一个方法。每一个套接字都用一个半相关描述：{协议，本地地址、本地端口}来表示；一个完整的套接字则用一个相关描述：{协议，本地地址、本地端口、远程地址、远程端口}，每一个套接字都有一个本地的由操作系统分配的唯一的套接字号。<br><br>3、&nbsp;Socket的三种类型<br>（1）&nbsp;流式Socket（SOCK_STREAM）<br>流式套接字提供可靠的、面向连接的通信流；它使用TCP协议，从而保证了数据传输的正确性和顺序的。<br>（2）&nbsp;数据报Socket（SOCK_DGRAM）<br>数据报套接字定义了一种无连接的服务，数据通过相互独立的报文进行传输，是无序的，并且不保证可靠、无差错。它使用数据报协议UDP<br>（3）&nbsp;原始Socket<br>原始套接字允许对底层协议如IP或ICMP直接访问，它功能强大但使用较为不便，主要用于一些协议的开发。<br><br>4、&nbsp;利用套接字发送数据<br>1、&nbsp;对于流式套接字用系统调用send（）来发送数据。<br>2、&nbsp;对于数据报套接字，则需要自己先加一个信息头，然后调用sendto（）函数把数据发送出去。<br><br>5、&nbsp;Linux中Socket的数据结构<br>（1）&nbsp;struct&nbsp;sockaddr&nbsp;{&nbsp;//用于存储套接字地址<br>unsigned&nbsp;short&nbsp;sa_family；//地址类型<br>char&nbsp;sa_data[14]；&nbsp;//14字节的协议地址<br>}；<br>（2）&nbsp;struct&nbsp;sockaddr_in{&nbsp;//in&nbsp;代表internet<br>short&nbsp;int&nbsp;sin_family；&nbsp;//internet协议族<br>unsigned&nbsp;short&nbsp;int&nbsp;sin_port；//端口号，必须是网络字节顺序<br>struct&nbsp;in_addr&nbsp;sin_addr；//internet地址，必须是网络字节顺序<br>unsigned&nbsp;char&nbsp;sin_zero；//添0（和struct&nbsp;sockaddr一样大小<br>}；<br>（3）&nbsp;struct&nbsp;in_addr{<br>unsigned&nbsp;long&nbsp;s_addr；<br>}；<br><br>6、&nbsp;网络字节顺序及其转换函数<br>（1）&nbsp;网络字节顺序<br>每一台机器内部对变量的字节存储顺序不同，而网络传输的数据是一定要统一顺序的。所以对内部字节表示顺序与网络字节顺序不同的机器，一定要对数据进行转换，从程序的可移植性要求来讲，就算本机的内部字节表示顺序与网络字节顺序相同也应该在传输数据以前先调用数据转换函数，以便程序移植到其它机器上后能正确执行。真正转换还是不转换是由系统函数自己来决定的。<br>（2）&nbsp;有关的转换函数<br>*&nbsp;unsigned&nbsp;short&nbsp;int&nbsp;htons（unsigned&nbsp;short&nbsp;int&nbsp;hostshort）：<br>主机字节顺序转换成网络字节顺序，对无符号短型进行操作4bytes<br>*&nbsp;unsigned&nbsp;long&nbsp;int&nbsp;htonl（unsigned&nbsp;long&nbsp;int&nbsp;hostlong）：<br>主机字节顺序转换成网络字节顺序，对无符号长型进行操作8bytes<br>*&nbsp;unsigned&nbsp;short&nbsp;int&nbsp;ntohs（unsigned&nbsp;short&nbsp;int&nbsp;netshort）：<br>网络字节顺序转换成主机字节顺序，对无符号短型进行操作4bytes<br>*&nbsp;unsigned&nbsp;long&nbsp;int&nbsp;ntohl（unsigned&nbsp;long&nbsp;int&nbsp;netlong）：<br>网络字节顺序转换成主机字节顺序，对无符号长型进行操作8bytes<br>注：以上函数原型定义在netinet/in.h里<br><br>7、&nbsp;IP地址转换<br>有三个函数将数字点形式表示的字符串IP地址与32位网络字节顺序的二进制形式的IP地址进行转换<br>（1）&nbsp;unsigned&nbsp;long&nbsp;int&nbsp;inet_addr(const&nbsp;char&nbsp;*&nbsp;cp)：该函数把一个用数字和点表示的IP地址的字符串转换成一个无符号长整型，如：struct&nbsp;sockaddr_in&nbsp;ina<br>ina.sin_addr.s_addr=inet_addr("202.206.17.101")<br>该函数成功时：返回转换结果；失败时返回常量INADDR_NONE，该常量=-1，二进制的无符号整数-1相当于255.255.255.255，这是一个广播地址，所以在程序中调用iner_addr（）时，一定要人为地对调用失败进行处理。由于该函数不能处理广播地址，所以在程序中应该使用函数inet_aton（）。<br>（2）int&nbsp;inet_aton（const&nbsp;char&nbsp;*&nbsp;cp,struct&nbsp;in_addr&nbsp;*&nbsp;inp）：此函数将字符串形式的IP地址转换成二进制形式的IP地址；成功时返回1，否则返回0，转换后的IP地址存储在参数inp中。<br>（3）&nbsp;char&nbsp;*&nbsp;inet_ntoa（struct&nbsp;in-addr&nbsp;in）：将32位二进制形式的IP地址转换为数字点形式的IP地址，结果在函数返回值中返回，返回的是一个指向字符串的指针。<br><br>8、&nbsp;字节处理函数<br>Socket地址是多字节数据，不是以空字符结尾的，这和C语言中的字符串是不同的。Linux提供了两组函数来处理多字节数据，一组以b（byte）开头，是和BSD系统兼容的函数，另一组以mem（内存）开头，是ANSI&nbsp;C提供的函数。<br>以b开头的函数有：<br>（1）&nbsp;void&nbsp;bzero（void&nbsp;*&nbsp;s,int&nbsp;n）：将参数s指定的内存的前n个字节设置为0，通常它用来将套接字地址清0。<br>（2）&nbsp;void&nbsp;bcopy（const&nbsp;void&nbsp;*&nbsp;src，void&nbsp;*&nbsp;dest，int&nbsp;n）：从参数src指定的内存区域拷贝指定数目的字节内容到参数dest指定的内存区域。<br>（3）&nbsp;int&nbsp;bcmp（const&nbsp;void&nbsp;*&nbsp;s1，const&nbsp;void&nbsp;*&nbsp;s2，int&nbsp;n）：比较参数s1指定的内存区域和参数s2指定的内存区域的前n个字节内容，如果相同则返回0，否则返回非0。<br>注：以上函数的原型定义在strings.h中。<br>以mem开头的函数有：<br>（1）&nbsp;void&nbsp;*&nbsp;memset（void&nbsp;*&nbsp;s，int&nbsp;c，size_t&nbsp;n）：将参数s指定的内存区域的前n个字节设置为参数c的内容。<br>（2）&nbsp;void&nbsp;*&nbsp;memcpy（void&nbsp;*&nbsp;dest，const&nbsp;void&nbsp;*&nbsp;src，size_t&nbsp;n）：功能同bcopy（），区别：函数bcopy（）能处理参数src和参数dest所指定的区域有重叠的情况，memcpy（）则不能。<br>（4）&nbsp;int&nbsp;memcmp（const&nbsp;void&nbsp;*&nbsp;s1，const&nbsp;void&nbsp;*&nbsp;s2，size_t&nbsp;n）：比较参数s1和参数s2指定区域的前n个字节内容，如果相同则返回0，否则返回非0。<br>注：以上函数的原型定义在string.h中。<br><br>9、&nbsp;基本套接字函数<br>（1）&nbsp;socket（）<br>#include&lt;&nbsp;sys/types.h&gt;&nbsp;<br>#include&lt;&nbsp;sys/socket.h&gt;&nbsp;<br>int&nbsp;socket(int&nbsp;domain，int&nbsp;type，int&nbsp;protocol)<br>参数domain指定要创建的套接字的协议族，可以是如下值：<br>AF_UNIX&nbsp;//UNIX域协议族，本机的进程间通讯时使用<br>AF_INET&nbsp;//Internet协议族（TCP/IP）<br>AF_ISO&nbsp;//ISO协议族<br>参数type指定套接字类型，可以是如下值：<br>SOCK_STREAM&nbsp;//流套接字，面向连接的和可靠的通信类型<br>SOCK_DGRAM&nbsp;//数据报套接字，非面向连接的和不可靠的通信类型<br>SOCK_RAW&nbsp;//原始套接字，只对Internet协议有效，可以用来直接访问IP协议<br>参数protocol通常设置成0，表示使用默认协议，如Internet协议族的流套接字使用TCP协议，而数据报套接字使用UDP协议。当套接字是原始套接字类型时，需要指定参数protocol，因为原始套接字对多种协议有效，如ICMP和IGMP等。<br>Linux系统中创建一个套接字的操作主要是：在内核中创建一个套接字数据结构，然后返回一个套接字描述符标识这个套接字数据结构。这个套接字数据结构包含连接的各种信息，如对方地址、TCP状态以及发送和接收缓冲区等等，TCP协议根据这个套接字数据结构的内容来控制这条连接。<br>（2）&nbsp;函数connect（）<br>#include&lt;&nbsp;sys/types.h&gt;&nbsp;<br>#include&lt;&nbsp;sys/socket.h&gt;&nbsp;<br>int&nbsp;connect（int&nbsp;sockfd，struct&nbsp;sockaddr&nbsp;*&nbsp;servaddr，int&nbsp;addrlen）<br>参数sockfd是函数socket返回的套接字描述符；参数servaddr指定远程服务器的套接字地址，包括服务器的IP地址和端口号；参数addrlen指定这个套接字地址的长度。成功时返回0，否则返回-1，并设置全局变量为以下任何一种错误类型：ETIMEOUT、ECONNREFUSED、EHOSTUNREACH或ENETUNREACH。<br>在调用函数connect之前，客户机需要指定服务器进程的套接字地址。客户机一般不需要指定自己的套接字地址（IP地址和端口号），系统会自动从1024至5000的端口号范围内为它选择一个未用的端口号，然后以这个端口号和本机的IP地址填充这个套接字地址。<br>客户机调用函数connect来主动建立连接。这个函数将启动TCP协议的3次握手过程。在建立连接之后或发生错误时函数返回。连接过程可能出现的错误情况有：<br>（1）&nbsp;如果客户机TCP协议没有接收到对它的SYN数据段的确认，函数以错误返回，错误类型为ETIMEOUT。通常TCP协议在发送SYN数据段失败之后，会多次发送SYN数据段，在所有的发送都高中失败之后，函数以错误返回。<br>注：SYN（synchronize）位：请求连接。TCP用这种数据段向对方TCP协议请求建立连接。在这个数据段中，TCP协议将它选择的初始序列号通知对方，并且与对方协议协商最大数据段大小。SYN数据段的序列号为初始序列号，这个SYN数据段能够被确认。当协议接收到对这个数据段的确认之后，建立TCP连接。<br>（2）&nbsp;如果远程TCP协议返回一个RST数据段，函数立即以错误返回，错误类型为ECONNREFUSED。当远程机器在SYN数据段指定的目的端口号处没有服务进程在等待连接时，远程机器的TCP协议将发送一个RST数据段，向客户机报告这个错误。客户机的TCP协议在接收到RST数据段后不再继续发送SYN数据段，函数立即以错误返回。<br>注：RST（reset）位：表示请求重置连接。当TCP协议接收到一个不能处理的数据段时，向对方TCP协议发送这种数据段，表示这个数据段所标识的连接出现了某种错误，请求TCP协议将这个连接清除。有3种情况可能导致TCP协议发送RST数据段：（1）SYN数据段指定的目的端口处没有接收进程在等待；（2）TCP协议想放弃一个已经存在的连接；（3）TCP接收到一个数据段，但是这个数据段所标识的连接不存在。接收到RST数据段的TCP协议立即将这条连接非正常地断开，并向应用程序报告错误。<br>（3）&nbsp;如果客户机的SYN数据段导致某个路由器产生&#8220;目的地不可到达&#8221;类型的ICMP消息，函数以错误返回，错误类型为EHOSTUNREACH或ENETUNREACH。通常TCP协议在接收到这个ICMP消息之后，记录这个消息，然后继续几次发送SYN数据段，在所有的发送都告失败之后，TCP协议检查这个ICMP消息，函数以错误返回。<br>注：ICMP：Internet&nbsp;消息控制协议。Internet的运行主要是由Internet的路由器来控制，路由器完成IP数据包的发送和接收，如果发送数据包时发生错误，路由器使用ICMP协议来报告这些错误。ICMP数据包是封装在IP数据包的数据部分中进行传输的，其格式如下：<br>类型<br>码&nbsp;<br>校验和<br>数据<br>0&nbsp;8&nbsp;16&nbsp;24&nbsp;31<br>类型：指出ICMP数据包的类型。<br>代码：提供ICMP数据包的进一步信息。<br>校验和：提供了对整个ICMP数据包内容的校验和。<br>ICMP数据包主要有以下类型：<br>（1）&nbsp;目的地不可到达：A、目的主机未运行；B、目的地址不存在；C、路由表中没有目的地址对应的条目，因而路由器无法找到去往目的主机的路由。<br>（2）&nbsp;超时：路由器将接收到的IP数据包的生存时间（TTL）域减1，如果这个域的值变为0，路由器丢弃这个IP数据包，并且发送这种ICMP消息。<br>（3）&nbsp;参数出错：当IP数据包中有无效域时发送。<br>（4）&nbsp;重定向：将一条新的路径通知主机。<br>（5）&nbsp;ECHO请求、ECHO回答：这两条消息用语测试目的主机是否可以到达。请求者向目的主机发送ECHO请求ICMP数据包，目的主机在接收到这个ICMP数据包之后，返回ECHO回答ICMP数据包。<br>（6）&nbsp;时戳请求、时戳回答：ICMP协议使用这两种消息从其他机器处获得其时钟的当前时间。<br><br>调用函数connect的过程中，当客户机TCP协议发送了SYN数据段的确认之后，TCP状态由CLOSED状态转为SYN_SENT状态，在接收到对SYN数据段的确认之后，TCP状态转换成ESTABLISHED状态，函数成功返回。如果调用函数connect失败，应该用close关闭这个套接字描述符，不能再次使用这个套接字描述符来调用函数connect。<br><br>注：TCP协议状态转换图：<br><br>被动OPEN&nbsp;CLOSE&nbsp;主动OPEN<br>（建立TCB）&nbsp;（删除TCB）&nbsp;（建立TCB，<br>发送SYN）<br>接收SYN&nbsp;SEND<br>（发送SYN，ACK）&nbsp;（发送SYN）<br><br>接收SYN的ACK（无动作）&nbsp;<br>接收SYN的ACK&nbsp;接收SYN，ACK&nbsp;<br>（无动作）&nbsp;（发送ACK）<br>CLOSE<br>（发送FIN）&nbsp;CLOSE&nbsp;接收FIN<br>（发送FIN）&nbsp;（发送FIN）<br><br>接收FIN<br>接收FIN的ACK（无动作）&nbsp;（发送ACK）&nbsp;CLOSE（发送FIN）<br><br><br>接收FIN&nbsp;接收FIN的ACK&nbsp;接收FIN的ACK<br>（发送ACK）&nbsp;（无动作）&nbsp;（无动作）<br><br>2MSL超时（删除TCB）&nbsp;<br>（3）&nbsp;函数bind（）<br>函数bind将本地地址与套接字绑定在一起，其定义如下：<br>#include&lt;&nbsp;sys/types.h&gt;&nbsp;<br>#include&lt;&nbsp;sys/socket.h&gt;&nbsp;<br>int&nbsp;bind(int&nbsp;sockfd,struct&nbsp;sockaddr&nbsp;*&nbsp;myaddr,int&nbsp;addrlen)；<br>参数sockfd是函数sockt返回的套接字描述符；参数myaddr是本地地址；参数addrlen是套接字地址结构的长度。执行成功时返回0，否则，返回-1，并设置全局变量errno为错误类型EADDRINUSER。<br>服务器和客户机都可以调用函数bind来绑定套接字地址，但一般是服务器调用函数bind来绑定自己的公认端口号。绑定操作一般有如下几种组合方式：<br>表1<br>程序类型<br>IP地址<br>端口号<br>说明<br>服务器<br>INADDR_ANY<br>非零值<br>指定服务器的公认端口号<br>服务器<br>本地IP地址<br>非零值<br>指定服务器的IP地址和公认端口号<br>客户机<br>INADDR_ANY<br>非零值<br>指定客户机的连接端口号<br>客户机<br>本地IP地址<br>非零值<br>指定客户机的IP地址连接端口号<br>客户机<br>本地IP地址<br>零<br>指定客户机的IP地址<br>分别说明如下：<br>（1）&nbsp;服务器指定套接字地址的公认端口号，不指定IP地址：即服务器调用bind时，设置套接字的IP地址为特殊的INADDE-ANY，表示它愿意接收来自任何网络设备接口的客户机连接。这是服务器最常用的绑定方式。<br>（2）&nbsp;服务器指定套接字地址的公认端口号和IP地址：服务器调用bind时，如果设置套接字的IP地址为某个本地IP地址，这表示这台机器只接收来自对应于这个IP地址的特定网络设备接口的客户机连接。当服务器有多块网卡时，可以用这种方式来限制服务器的接收范围。<br>（3）&nbsp;客户机指定套接字地址的连接端口号：一般情况下，客户机调用connect函数时不用指定自己的套接字地址的端口号。系统会自动为它选择一个未用的端口号，并且用本地的IP地址来填充套接字地址中的相应项。但有时客户机需要使用一个特定的端口号（比如保留端口号），而系统不会未客户机自动分配一个保留端口号，所以需要调用函数bind来和一个未用的保留端口号绑定。<br>（4）&nbsp;指定客户机的IP地址和连接端口号：表示客户机使用指定的网络设备接口和端口号进行通信。<br>（5）&nbsp;指定客户机的IP地址：表示客户机使用指定的网络设备接口和端口号进行通信，系统自动为客户机选一个未用的端口号。一般只有在主机有多个网络设备接口时使用。<br>我们一般不在客户机上使用固定的客户机端口号，除非是必须使用的情况。在客户机上使用固定的端口号有以下不利：<br>（1）&nbsp;服务器执行主动关闭操作：服务器最后进入TIME_WAIT状态。当客户机再次与这个服务器进行连接时，仍使用相同的客户机端口号，于是这个连接与前次连接的套接字对完全一样，但是一呢、为前次连接处于TIME_WAIT状态，并未消失，所以这次连接请求被拒绝，函connect以错误返回，错误类型为ECONNREFUSED<br>（2）&nbsp;客户机执行主动关闭操作：客户机最后进入TIME_WAIT状态。当马上再次执行这个客户机程序时，客户机将继续与这个固定客户机端口号绑定，但因为前次连接处于TIME_WAIT状态，并未消失，系统会发现这个端口号仍被占用，所以这次绑定操作失败，函数bind以错误返回，错误类型为EADDRINUSE。<br>（4）&nbsp;函数listen（）<br>函数listen将一个套接字转换为征听套接字，定义如下；<br>#include&lt;&nbsp;sys/socket,h&gt;&nbsp;<br>int&nbsp;listen(int&nbsp;sockfd，int&nbsp;backlog)<br>参数sockfd指定要转换的套接字描述符；参数backlog设置请求队列的最大长度；执行成功时返回0，&nbsp;否则返回-1。函数listen功能有两个：<br>（1）&nbsp;将一个尚未连接的主动套接字（函数socket创建的可以用来进行主动连接但不能接受连接请求的套接字）转换成一个被动连接套接字。执行listen之后，服务器的TCP状态由CLOSED转为LISTEN状态。<br>（2）&nbsp;TCP协议将到达的连接请求队列，函数listen的第二个参数指定这个队列的最大长度。<br>注：参数backlog的作用：<br>TCP协议为每一个征听套接字维护两个队列：<br>（1）&nbsp;未完成连接队列：每个尚未完成3次握手操作的TCP连接在这个队列中占有一项。TCP希望仪在接收到一个客户机SYN数据段之后，在这个队列中创建一个新条目，然后发送对客户机SYN数据段的确认和自己的SYN数据段（ACK+SYN数据段），等待客户机对自己的SYN数据段的确认。此时，套接字处于SYN_RCVD状态。这个条目将保存在这个队列中，直到客户机返回对SYN数据段的确认或者连接超时。<br>（2）&nbsp;完成连接队列：每个已经完成3次握手操作，但尚未被应用程序接收（调用函数accept）的TCP连接在这个队列中占有一项。当一个在未完成连接队列中的连接接收到对SYN数据段的确认之后，完成3次握手操作，TCP协议将它从未完成连接队列移到完成连接队列中。此时，套接字处于ESTABLISHED状态。这个条目将保存在这个队列中，直到应用程序调用函数accept来接收它。<br>参数backlog指定某个征听套接字的完成连接队列的最大长度，表示这个套接字能够接收的最大数目的未接收连接。如果当一个客户机的SYN数据段到达时，征听套接字的完成队列已经满了，那么TCP协议将忽略这个SYN数据段。对于不能接收的SYN数据段，TCP协议不发送RST数据段，<br>（5）&nbsp;函数accept（）<br>函数accept从征听套接字的完成队列中接收一个已经建立起来的TCP连接。如果完成连接队列为空，那么这个进程睡眠。<br>#include&lt;&nbsp;sys/socket.h&gt;&nbsp;<br>int&nbsp;accept(int&nbsp;sockfd，struct&nbsp;sockaddr&nbsp;*&nbsp;addr，int&nbsp;*&nbsp;addrlen)<br>参数sockfd指定征听套接字描述符；参数addr为指向一个Internet套接字地址结构的指针；参数addrlen为指向一个整型变量的指针。执行成功时，返回3个结果：函数返回值为一个新的套接字描述符，标识这个接收的连接；参数addr指向的结构变量中存储客户机地址；参数addrlen指向的整型变量中存储客户机地址的长度。失败时返回-1。<br>征听套接字专为接收客户机连接请求，完成3次握手操作而用的，所以TCP协议不能使用征听套接字描述符来标识这个连接，于是TCP协议创建一个新的套接字来标识这个要接收的连接，并将它的描述符发挥给应用程序。现在有两个套接字，一个是调用函数accept时使用的征听套接字，另一个是函数accept返回的连接套接字（connected&nbsp;socket）。一个服务器通常只需创建一个征听套接字，在服务器进程的整个活动期间，用它来接收所有客户机的连接请求，在服务器进程终止前关闭这个征听套接字；对于没一个接收的（accepted）连接，TCP协议都创建一个新的连接套接字来标识这个连接，服务器使用这个连接套接字与客户机进行通信操作，当服务器处理完这个客户机请求时，关闭这个连接套接字。<br>当函数accept阻塞等待已经建立的连接时，如果进程捕获到信号，函数将以错误返回，错误类型为EINTR。对于这种错误，一般重新调用函数accept来接收连接。<br>（6）&nbsp;函数close（）<br>函数close关闭一个套接字描述符。定义如下：<br>#include&lt;&nbsp;unistd.h&gt;&nbsp;<br>int&nbsp;close(int&nbsp;sockfd)；<br>执行成功时返回0，否则返回-1。与操作文件描述符的close一样，函数close将套接字描述符的引用计数器减1，如果描述符的引用计数大于0，则表示还有进程引用这个描述符，函数close正常返回；如果为0，则启动清除套接字描述符的操作，函数close立即正常返回。<br>调用close之后，进程将不再能够访问这个套接字，但TCP协议将继续使用这个套接字，将尚未发送的数据传递到对方，然后发送FIN数据段，执行关闭操作，一直等到这个TCP连接完全关闭之后，TCP协议才删除该套接字。<br>（7）&nbsp;函数read（）和write（）<br>用于从套接字读写数据。定义如下：<br>int&nbsp;read(int&nbsp;fd，char&nbsp;*&nbsp;buf，int&nbsp;len)<br>int&nbsp;write(int&nbsp;fd，char&nbsp;*&nbsp;buf，int&nbsp;len)<br>函数执行成功时，返回读或写的数据量的大小，失败时返回-1。<br>每个TCP套接字都有两个缓冲区：套接字发送缓冲区、套接字接收缓冲区，分别处理发送和接收任务。从网络读、写数据的操作是由TCP协议在内核中完成的：TCP协议将从网络上接收到的数据保存在相应套接字的接收缓冲区中，等待用户调用函数将它们从接收缓冲区拷贝到用户缓冲区；用户将要发送的数据拷贝到相应套接字的发送缓冲区中，然后由TCP协议按照一定的算法处理这些数据。<br>读写连接套接字的操作与读写文件的操作类似，也可以使用函数read和write。函数read完成将数据从套接字接收缓冲区拷贝到用户缓冲区：当套接字接收缓冲区有数据可读时，1：可读数据量大于函数read指定值，返回函数参数len指定的数据量；2：了度数据量小于函数read指定值，函数read不等待请求的所有数据都到达，而是立即返回实际读到的数据量；当无数据可读时，函数read将阻塞不返回，等待数据到达。<br>当TCP协议接收到FIN数据段，相当于给读操作一个文件结束符，此时read函数返回0，并且以后所有在这个套接字上的读操作均返回0，这和普通文件中遇到文件结束符是一样的。<br>当TCP协议接收到RST数据段，表示连接出现了某种错误，函数read将以错误返回，错误类型为ECONNERESET。并且以后所有在这个套接字上的读操作均返回错误。错误返回时返回值小于0。<br>函数write完成将数据从用户缓冲区拷贝到套接字发送缓冲区的任务：到套接字发送缓冲区有足够拷贝所有用户数据的空间时，函数write将数据拷贝到这个缓冲区中，并返回老辈的数量大小，如果可用空间小于write参数len指定的大小时，函数write将阻塞不返回，等待缓冲区有足够的空间。<br>当TCP协议接收到RST数据段（当对方已经关闭了这条连接之后，继续向这个套接字发送数据将导致对方TCP协议返回RST数据段），TCP协议接收到RST数据段时，函数write将以错误返回，错误类型为EINTR。以后可以继续在这个套接字上写数据。<br>（8）&nbsp;函数getsockname（）和getpeername（）<br>函数getsockname返回套接字的本地地址；函数getpeername返回套接字对应的远程地址。<br><br>10、&nbsp;结束语<br>网络程序设计全靠套接字接收和发送信息。上文主要讲述了Linux&nbsp;下Socket的基本概念、Sockets&nbsp;API以及Socket所涉及到的TCP常识 
<img src ="http://www.cppblog.com/tx7do/aggbug/5962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:40 <a href="http://www.cppblog.com/tx7do/articles/5962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket编程—技术实现</title><link>http://www.cppblog.com/tx7do/articles/5961.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:36:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5961.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5961.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5961.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5961.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5961.html</trackback:ping><description><![CDATA[
		<span class="tpc_content">
				<font size="2">这几天都在玩socket了，有一点心得，贴出来与大家共赏，若有不妥或错误的地方，还请各位看官指点一二。<br /><br />什么是socket？socket就是...，我在这里就不抄书了，有兴趣的同仁去查查书吧。<br />不过还要说一句，socket就是不同进程之间的一种通信方式。就象打电话是朋友之间的一种通信方式是一样。个人理解：所谓“通信”，就是相互之间发送数据。有人理解socket是不同计算机之间的一种通信方<br />式，这是不确切的。两个进程，不管是运行在同一台计算机上，还是运行在不同计算机上，都可通过<br />socket技术进行通信。<br /><br />socket套接字的使用需要有网卡的支持，所以socket一般都被用来在不同机器之间通信，而如果在同一台计算机上的两个进程进行通信，通常采用效率更高的共享内存技术来实现。<br /><br />两个进程之间进行通讯，就需要两个进程同时都在运行了（废话），在具体实现中，两个进程我们通常要区别对待，一个进程专门等待另一个进程给自己发消息，收到消息后进行处理，在把处理结果发送回去。我们把专门处理消息、提供服务的进程称为服务器端，把发送消息、请求处理的进程称为客户端。总体过程就是客户端发送一个消息给服务器端，服务器端进程收到消息进行处理，把处理结果发送给客户端。恩，就是这样。<br /><br />还有一个问题，如果我现在有一个进程要跟另一台计算机上的某个进程进行socket通信，那在我这个进程中如何指定另一个进程呢？这里还需要说一下另一个概念——端口，如果把操作系统比作一座房子的话，那端口就是房子的窗口，是系统外界同系统内部进行通信的通道。在socket实现中，我们不进行另一个进程的指定，而是指定发送消息或接收消息的端口号。比如说现在进程A要给进程B发消息，我们会把消息发送到进程B所运行的计算机的端口N上，而进程B此时正在监视端口N，这样进程B就能收到进程A发送来的数据，同样进程B也把消息发送到该端口上，进程A也能从该端口收到进程B发送来的数据，当然，这需要客户端和服务器端关于端口号进行一个约定，即共同操作同一个端口。如果客户端把消息发送到端口N1上，而服务器端监视的是端口N2，那通信一定不能成功。端口号最大为65535，不能比这个再大了，但在我们自己的程序中尽量不要用小于1024的端口号，小于1024的端口好很多都被系统使用了，比如23被telnet所使用。<br /><br />socket的实现是很简单的，只要按照一定的步骤，就可马上建立一个这样的通信通道。<br /><br />下面较详细的介绍几个核心的函数：<br /><br />SOCKET socket(int af, int type, int protocol);<br />无论是客户端还是服务器端，下面这个函数是一定要用到的，也是最先用到的。<br />这个函数是要告诉系统，给我准备好一个socket通道，我要和其它进程通信了。函数的返回值很重要，我们要记下来，它表示系统为我们准备好的这个socket通道，在以后的每个socket相关函数中都会用到，如果这个值等于SOCKET_ERROR，表示函数执行失败了。函数的参数我们分别给：PF_INET、SOCK_STREAM和IPPROTO_TCP。<br /><br />int bind(SOCKET s, const sockaddr *addr, int namelen);<br />这个函数只有服务器端程序使用，作用是与某个socket通道绑定。可以用返回值判断该函数执行结果怎么样，如果等于SOCKET_ERROR，那就是失败了。第一个参数s，就是socket()函数的返回值；在结构addr中，我们要给定一个端口号；namelen等于结构sockaddr的大小。<br /><br />int listen(SOCKET s, int backlog);<br />这个函数只有服务器端程序使用，作用是监听该端口。返回值与bind函数意义一样。<br /><br />int accept(SOCKET s, sockaddr *addr, int *addrlen);<br />这个函数只有服务器端程序使用，作用是响应客户端的连接。返回值与bind函数意义一样。<br /><br />int connect(SOCKET s, const sockaddr *name, int namelen);<br />这个函数只有客户端程序使用，作用是把客户端和某个计算机的某个端口建立连接。返回值与bind函数意义一样。第一个参数s，就是socket()函数的返回值；在结构name中，我们要给定一个端口号和目的机器名；namelen等于结构sockaddr的大小。<br /><br />int send(SOCKET s, char *buf, int len, int flags);<br />int recv(SOCKET s, char *buf, int len, int flags);<br />这两个函数就是发送数据和接收数据，客户端和服务器端程序都能用，哪个发送哪个接收不用说了吧？呵呵。<br />从函数的返回值可以检查函数执行是否成功。参数中buf是指向发送或接收的数据的指针，len是数据长度。flags我们给个0就可以（其实是我不知道具体含义）。<br /><br />最后就是关闭socket了，这个很容易忘掉，但这个函数很重要，一定要用。<br />int closesocket(SOCKET s);<br /><br /><br />好了，关键函数就这么几个，下图是这几个函数的执行顺序：<br /><br />client端 service端<br /><br />  |     |<br />  v     v<br />socket() socket()<br />  |     |<br />  |     v<br />  |   bind()<br />  |     |<br />  |     v<br />  |   listen()<br />  |     |<br />  |     v<br />  |   accept() 挂起，直到有客户端来连接<br />  |     |<br />  v   三段握手过程   |<br />connect() &lt;-------------&gt; |<br />  |     |<br />  v   发送消息   v<br />  +---&gt; send() ---------------&gt; recv() &lt;-------+<br />  |   |     . |<br />  |   |     . 处理消息 |<br />  |   v   响应消息   . |<br />  +---- recv() &lt;--------------- send() --------+<br />  |     |<br />  v     |<br />close() ---------------&gt; recv()<br />    |<br />    v<br />  closesocket()<br /><br />上图我觉得能很好的说明客户端和服务器端的运行轨迹。<br /><br />使用以上几个函数在 linux 系统上就可成功建立一个socket通信连路，但如果在windows系统上，还要用到另一个函数：<br />int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);<br />在windows系统上，首先要执行这个函数，所以要把这个函数放在socket()函数的前面。<br /><br />我对上面的函数进行了一些封装，为节省篇幅，我去掉所有注释和非重要的函数，在这里可以看到各个函数的具体用法：<br /><br />在 VC60 环境下要运行下面的函数，要包含头文件 errno.h 和 winsock2.h，还有，在连接的时候要连接上ws2_32.dll文件。<br /><br />这是头文件内容：<br />class Socket {<br />public:<br /><br />bool setup();<br /><br />void close();<br /><br />bool connect(string host, int port);<br /><br />bool listen();<br /><br />int accept();<br /><br />int recv(char *buf, int len);<br /><br />int recv(int new_fd, char *buf, int len);<br /><br />int send(const char *msg, int len);<br /><br />int send(int new_fd, const char *msg, int len);<br /><br />private:<br />  int _fd;<br />};<br /><br />这是实现文件内容：<br />bool Socket::setup() {<br /><br />WSADATA wsd;<br />_fd = WSAStartup(MAKEWORD(2,2), &amp;wsd); <br />if(_fd) {<br />return false;<br />}<br /><br />_fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);<br />if (_fd == -1) {<br />return false;<br />}<br />return true;<br />}<br /><br />bool Socket::listen() {<br />struct sockaddr_in my_addr;<br /><br />my_addr.sin_family = AF_INET; <br />my_addr.sin_port = htons(52309);<br />my_addr.sin_addr.s_addr = INADDR_ANY;<br /><br />if(::bind(_fd, (struct sockaddr *)&amp;my_addr, sizeof(struct sockaddr)) == SOCKET_ERROR) {<br />return false;<br />}<br /><br />if(::listen(_fd, BACKLOG) == SOCKET_ERROR) {<br />return false;<br />}<br /><br />return true;<br />}<br /><br />int Socket::accept()<br />{<br />int new_fd;<br />struct sockaddr_in their_addr;<br />int sin_size = sizeof(their_addr);<br /><br />printf("accepting... \n");<br /><br />new_fd = ::accept(_fd, <br />  (struct sockaddr *)&amp;their_addr,<br />  &amp;sin_size);<br />return new_fd == SOCKET_ERROR ? -1:new_fd;<br />}<br /><br />bool Socket::connect(string host, int port) {<br />struct hostent *_h = gethostbyname(host.c_str());<br />if (_h == 0) {<br />return false;<br />}<br /><br />struct in_addr *_addr = (struct in_addr *)_h-&gt;h_addr;<br />struct sockaddr_in sin;<br />sin.sin_family = AF_INET;<br />sin.sin_addr = *_addr;<br />sin.sin_port = htons(port);<br /><br />if (::connect(_fd, (sockaddr *)&amp;sin, sizeof(sin)) == SOCKET_ERROR) {<br />return false;<br />}<br /><br />return true;<br />}<br /><br />int Socket::recv(int new_fd, char *buf, int len)<br />{<br />int nb = ::recv(new_fd, buf, len, 0);<br />if (nb == -1) {<br />printf("Error! recv.\n");<br />}<br />return nb;<br />}<br /><br />int Socket::recv(char *buf, int len) {<br />return recv(_fd, buf, len);<br />}<br /><br />int Socket::send(const char *msg, int len) {<br />return send(_fd, msg, len);<br />}<br /><br />int Socket::send(int new_fd, const char *msg, int len)<br />{<br />int nb = ::send(new_fd, msg, len, 0);<br />if (nb == -1) {<br />printf("Error! send.\n");<br />}<br /><br />return nb;<br />}<br /><br />void Socket::close() {<br /><br />int trytimes = 0;<br />while(::closesocket(_fd) &amp;&amp; trytimes &lt; CLOSE_TRY_TIMES)<br />trytimes++;<br /><br />if(trytimes == 10) {<br />printf("Cannot close socket!\n");<br />}<br />}<br /><br />好，socket类是封装好了，下面就是组织了，服务器端和客户端是不一样的，下面分别给出代码，到这里已经就很简单了。<br /><br />客户端：<br />int main(int argc, char **argv)<br />{<br />printf("socket of client is run ...\n");<br />Socket s;<br />if (!s.connect("dezhi", 52309))<br />return 0;<br /><br />char *msg = "ok, send a message.";<br />for (int i=0; i&lt;10; i++) {<br />s.send(msg, 20);<br />printf("message = %s\n", msg);<br />}<br />s.send("q", 1);<br />s.close();<br /><br />return 0;<br />}<br /><br />服务器：<br />int main(int argc, char **argv) {<br />printf("socket of service is run ...\n");<br /><br />Socket s;<br />s.listen();<br />int new_fd = s.accept();<br /><br />char buf[8];<br />buf[7] = '\0';<br />while (1) {<br />if (s.recv(new_fd, buf, 5) != -1) {<br />  printf("%s\n", buf);<br />  if (buf[0] == 'q')<br />  break;<br />}<br />}<br />s.close();<br />}<br /><br />下面为运行结果：<br />客户端：<br />socket of client is run ...<br />Socket: WSAStartup success execute.<br />Socket: socket success execute.<br />Socket: Establish the connection to "127.0.0.1:52309"<br />message = ok, send a message.<br />message = ok, send a message.<br />message = ok, send a message.<br />message = ok, send a message.<br />message = ok, send a message.<br />message = ok, send a message.<br />message = ok, send a message.<br />message = ok, send a message.<br />message = ok, send a message.<br />message = ok, send a message.<br />Socket: Close connection to "127.0.0.1:52309"<br />Press any key to continue<br /><br />服务器端<br />socket of service is run ...<br />Socket: WSAStartup success execute.<br />Socket: socket success execute.<br />bind ok!<br />listen ok!<br />accepting...<br />ok, send a message.<br />ok, send a message.<br />ok, send a message.<br />ok, send a message.<br />ok, send a message.<br />ok, send a message.<br />ok, send a message.<br />ok, send a message.<br />ok, send a message.<br />ok, send a message.<br />qk, send a message.<br />Press any key to continue<br /><br />就到这里吧。socket的相关内容可远不止这些，我在这里只是给大家来个抛砖引玉，想深究？路还很漫长。关于详细的实现代码，去我的《源码》上找吧，不放在这里，是为了让篇幅小些。</font>
		</span>
		<br />
<img src ="http://www.cppblog.com/tx7do/aggbug/5961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:36 <a href="http://www.cppblog.com/tx7do/articles/5961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket编程</title><link>http://www.cppblog.com/tx7do/articles/5960.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:34:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5960.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5960.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5960.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5960.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5960.html</trackback:ping><description><![CDATA[socket类型(在sys/socket.h中)<br /><br />int SOCK_STREAM<br />先连接到一台主机然后用流方式传送数据<br /><br />int SOCK_DGRAM<br />不连接,在数据包中包含目标地址,然后直接送出,包在传送过程中可能丢失和错位<br /><br />int SOCK_RAW<br />socket数据的底层传输,对于一般程序没有什么意义<br /><br /><br />地址的表示方法<br /><br />相关库:sys/socket.h<br />相关数据结构:struct sockaddr *<br />sockaddr中的两个元素:<br />===short int sa_family:指出地址的格式<br />===char sa_data[14]:地址值<br /><br /><br /><br />地址的格式:<br />AF_LOCAL:本地名称空间(name space)的地址<br />AF_UNIX:和AF_LOCAL相同,但AF_UNIX是UNIX98标准<br />AF_FILE:AF_LOCAL的另一个同义词<br />AF_INET:互联网名称空间,对应的名称空间名为PF_INET<br />AF_INET6:IPv6互联网名称空间<br />AF_UNSPEC:用到的地方很少,比如清除"带连接"的DATAGRAM的目标地址等,对应的名称空间在新版本的libc中已经被去处<br /><br /><br /><br />设置socket地址(在sys/socket.h中)<br /><br />使用bind函数将某个地址分配给某个socket<br />int bind(int socket,struct sock_addr *addr,socklen_t length);<br />将length长度的地址sock_addr分配给socket<br />返回0代表成功,返回-1代表失败<br /><br /><br /><br />读取socket分配到的地址(在sys/socket.h中)<br /><br />使用getsockname函数来得到一个socket对应的地址<br />int getsockname(int socket,struct sockaddr *addr,socklen_t *length-ptr);<br />将socket中的信息放置到*addr和*length-ptr所指定的空间中<br />返回值0表示成功-1表示失败<br /><br /><br /><br />网络界面Interface的相关变量和函数<br /><br />以下内容在库文件net/if.h中<br /><br />size_t IFNAMSIZ<br />表示出容纳界面名称的缓冲区的大小,包括结束符0<br /><br />unsigned int nametoindex(const char *ifname);<br />返回ifname所指出的网络界面的序号,返回0表示此界面不存在<br /><br />char *if_indextoname(unsigned int ifindex,char *ifname);<br />找到一个网络界面序号对应的界面名称,返回值在ifname对应的那段内存空间上,这段空间至少有IFNAMSIZ大,返回ifname表示成功,返回NULL表示失败<br /><br />struct if_nameindex<br />这个变量用于存储单个网络界面的信息,其中具有两个元素:<br />unsigned int if_index:界面序号<br />char *if_name:用null结尾的界面名称<br /><br />struct if_nameindex *if_nameindex(void);<br />返回一个struct if_nameindex列表,其中存储了所有界面的信息,最后一个if_nameindex的if_index序号为零,if_name为null<br />此函数得到的结果必需用if_freenameindex函数清除<br /><br />void if_freenameindex(struct if_nameindex *ptr);<br />清除if_nameindex得到的结果<br /><br /><br /><br />本地名称空间(local namespace)<br /><br />本地名称空间表示为PF_LOCAL(POSIX),PF_UNIX,PF_FILE<br /><br />本地名称是一个文件名,只能本地调用不能从其他主机上连接<br /><br />本地socket结构(在sys/socket.h中)<br />struct sockaddr_un<br />其中包含的元素为<br />short int sun_family:地址的格式应当设为AF_LOCAL<br />char sun_path[108]:所要使用的文件的文件名(暂时定为108位，可能新的版本中会有所改变)<br /><br />sun_len函数:<br />int SUN_LEN(struct sun family *);<br />具体说应当是SUN_LEN宏，用来统计某个sockaddr_un结构的元素长度和文件名长度(不是分配的字节空间的长度)<br /><br /><br /><br />一个创建本地socket的例子<br />#include &lt;stddef.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;errno.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;sys/socket.h&gt;<br />#include &lt;sys/un.h&gt;<br />int make_named_socket (const char *filename)//此函数作用是用filename创建socket<br />{<br />  struct sockaddr_un name;//socket地址名name<br />  int sock;               //socket<br />  size_t size;<br /><br />  /* Create the socket. */<br />  sock = socket (PF_LOCAL, SOCK_DGRAM, 0);//PF_LOCAL表示本地socket<br />                                          //SOCK_DGRAM表示数据报方式<br />  if (sock &lt; 0)//如创建失败则报错<br />    {<br />      perror ("socket"<img onclick="window.open('/images/wink.gif','_blank');" hspace="2" src="http://www.blogcn.com/images/wink.gif" onload="javascript:if(this.width&gt;screen.width/2)this.width=screen.width/2" vspace="2" border="0" />;<br />      exit (EXIT_FAILURE);<br />    }<br /><br />  /* Bind a name to the socket. */<br />  name.sun_family = AF_LOCAL;<br />  strncpy (name.sun_path, filename, sizeof (name.sun_path));<br /><br />  /* 地址的长度为sockaddr<br />     结构中filename开始端的偏移量<br />     加上filename中文件名的长度<br />     加上一个字节(此字节为结束标识)<br />     或者还可以用宏SUN_LEN:<br />     size = SUN_LEN (&amp;name);<br /> */<br />  size = (offsetof (struct sockaddr_un, sun_path)<br />          + strlen (name.sun_path) + 1);//开始计算<br /><br />  if (bind (sock, (struct sockaddr *) &amp;name, size) &lt; 0)<br />    {<br />      perror ("bind"<img onclick="window.open('/images/wink.gif','_blank');" hspace="2" src="http://www.blogcn.com/images/wink.gif" onload="javascript:if(this.width&gt;screen.width/2)this.width=screen.width/2" vspace="2" border="0" />;<br />      exit (EXIT_FAILURE);<br />    }<br /><br />  return sock;<br />}<br /><br /><br /><br />关于生成主机地址的函数<br /><br />inet_aton(const char *name,struct in_addr *addr);<br />将以字符串表示的地址转换成主机地址并储存在struct in_addr中<br /><br />uint32_t inet_addr(const char *name);<br />将字符串IPv4地址转换成主机地址并返回,如失败则返回INADDR_NONE(255.255.255.255);<br /><br />uint32_t inet_network(const char *name);<br />将停用<br /><br />char *inet_ntoa(struct in_addr addr);<br />将IPv4主机地址转换成字符串<br />注意:此函数的返回的字符串存储在一段static类型的内存空间中,下次调用会覆盖原先的结果,在多线程程序的运行中会出现混乱,所以推荐使用下文中介绍的inet_ntop<br /><br />struct in_addr inet_makeaddr(uint32_t net,uint32_t local);<br />将网络号net和主机名local组合成IPv4主机地址并返回<br /><br />uint32_t inet_lnaof(struct in_addr addr);<br />从IPv4网络地址中取出主机名并返回(将停用)<br /><br />uint32_t inet_netof(struct in_addr addr);<br />从IPv4网络地址中取出网络号并返回(将停用)<br /><br />int inet_pton(int af,const char *cp,void *buf);<br />将IPv4或IPv6字符串地址转换成网络主机地址<br />af:网络地址的格式,可取值为AF_INET和AF_INET6<br />cp:指向字符串首地址的指针<br />buf:指向结果存储空间的指针(应当预先分配好足够的内存空间存储结果)<br /><br />const char *inet_ntop(int af,const void *cp,char *buf,size_t len);<br />将IPv4或IPv6网络主机地址转换成字符串<br />af:网络地址的格式,可取数为AF_INET和AF_INET6<br />cp:指向需要转换的网络地址<br />buf:指向存储转换结果的内存空间<br />len:buf所指向的空间的长度<br />返回值为buf<br /><br /><br /><br />主机名数据库查询的相关变量<br /><br />struct hostent<br />其中元素:<br />char *h_name:主机的"官方"名称<br />char **h_aliases:此主机的所有别名<br />int h_addrtype:地址类型,可以为AF_INET(IPv4类)和AF_INET6(IPv6类),也可以出现别的值<br />int h_length:地址的大小(用字节数计算)<br />char **h_addr_list:此主机名对应的所有IP,以一个null指针结束<br />char *h_addr:等于h_addr_list[0]<br /><br /><br /><br />主机名和数据库查询相关函数<br /><br />struct hostent *gethostbyname(const char *name);<br />返回主机名name的信息,如果查询失败则返回一个null指针<br /><br />struct hostent *gethostbyname2(const char *name,int af);<br />和gethostbyname相通,不过可以在af中指出地址格式,可取AF_INET或AF_INET6,分别代表IPv4和IPv6<br /><br />struct hostent *gethostbyaddr(const char *addr,size_t length,int format);<br />返回指定网络主机的信息,addr并非指向字符串而是指向一个网络地址,length为addr中地址的长度,format为地址的格式(可取AF_INET或AF_INET6)<br /><br /><br /><br />创建socket<br /><br />所需函数<br />int socket(int namespace,int style,int protocol);<br />namespace:socket类型(比如PF_LOCAL和PF_INET)<br />style:传输方式(可取SOCK_STREAM和SOCK_DGRAM)<br />protocol:协议,一般取0<br /><br /><br /><br />关闭socket<br /><br />所需函数<br />int shutdown(int socket,int how);<br />关闭socket<br />返回0成功,返回-1失败<br />how可取值为<br />0:停止接收数据<br />1:停止送出数据<br />2:停止接收和读取<br /><br /><br /><br />socket对(socket pair)<br /><br />两个可以互相传送的本地socket,和pipe类似,不过pipe为单向,socket对为双向<br /><br />创造socket对所需函数<br />int socketpair(int namespace,int style,int protocol,int filedes[2]);<br />namespace:必需为AF_LOCAL<br />style:可以取SOCK_STREAM或者SOCK_DGRAM<br />filedes[2]:创建的socket对放在这里<img src ="http://www.cppblog.com/tx7do/aggbug/5960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:34 <a href="http://www.cppblog.com/tx7do/articles/5960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Socket学习笔记之一（常用基本定义） </title><link>http://www.cppblog.com/tx7do/articles/5956.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:28:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5956.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5956.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5956.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5956.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<p>常用类型的定义：<br />（以下定义从Winsock2.h文件中截取）<br />/*<br /> * The new type to be used in all<br /> * instances which refer to sockets.<br /> */<br />typedef UINT_PTR        SOCKET;<font color="#0000ff">//SOCKET原来就是一个unsigned int的指针而已</font></p>
				<p>/*<br /> * Select uses arrays of SOCKETs.  These macros manipulate such<br /> * arrays.  FD_SETSIZE may be defined by the user before including<br /> * this file, but the default here should be &gt;= 64.<br /> *<br /> * CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE<br /> * INCLUDED IN WINSOCK2.H EXACTLY AS SHOWN HERE.<br /> */<br />#ifndef FD_SETSIZE<br />#define FD_SETSIZE      64<br />#endif /* FD_SETSIZE */<br />typedef struct fd_set {<br />        u_int fd_count;               /* how many are SET? */<br />        SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */<br />} fd_set<font color="#0000ff">;//fd_set是用来select的，表示一个集合，STL中不是有个模板类set么<br />//对fd_set结构，Winsock2.h中还定义了四个宏定义来操作fd_set<br />//FD_CLR(fd, set),FD_SET(fd, set),FD_ZERO(set),FD_ISSET(fd, set)<br />//一般用法是先定义一个fd_set,使用之前调用fd_zero，再将一个socket放到fd_set中<br />//经过一系列操作后，用fd_isset判断某个socket是否还在set中。<br />//SOCKET fd;<br />//......<br />//fd_set ReadFds;<br />//FD_ZERO(&amp;ReadFds);<br />//FD_SET(fd,&amp;ReadFds);<br />//.....<br />//if ( FD_ISSET(fd,&amp;ReadFds) )<br />//.....<br /></font>/*<br /> * Structure used in select() call, taken from the BSD file sys/time.h.<br /> */<br />struct timeval {<br />        long    tv_sec;         /* seconds */<br />        long    tv_usec;        /* and microseconds */<br /><font color="#0000ff">};//这个也是用于select函数中的，超时参数<br /></font>struct  hostent <font color="#0000ff">{//表示主机的结构<br /></font>        char    FAR * h_name;           /* official name of host */<br />        char    FAR * FAR * h_aliases;  /* alias list */<br />        short   h_addrtype;             /* host address type */<br />        short   h_length;               /* length of address */<br />        char    FAR * FAR * h_addr_list; /* list of addresses */<br />#define h_addr  h_addr_list[0]          /* address, for backward compat */<br />};<br />/*<br /> * Internet address (old style... should be updated<font color="#0000ff">)//晕，什么时候update？<br /> *///原来每次看到in_addr结构都不知道为什么叫in_addr,原来是这样。。。<br /></font>struct in_addr {<br />        union {<br />                struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;<br />                struct { u_short s_w1,s_w2; } S_un_w;<br />                u_long S_addr; <font color="#0000ff">//大部分都用这个变量就够了（一个ip地址32位刚好一个unsigned long）<br /></font>        } S_un;<br />#define s_addr  S_un.S_addr <font color="#0000ff">//这样定义以后用的很方便，in_addr.s_addr就可以了。<br /></font>                                /* can be used for most tcp &amp; ip code */<br />#define s_host  S_un.S_un_b.s_b2<br />                                /* host on imp */<br />#define s_net   S_un.S_un_b.s_b1<br />                                /* network */<br />#define s_imp   S_un.S_un_w.s_w2<br />                                /* imp */<br />#define s_impno S_un.S_un_b.s_b4<br />                                /* imp # */<br />#define s_lh    S_un.S_un_b.s_b3<br />                                /* logical host */<br />};<br /><font color="#0000ff">//这b1，b2，b3，b4，w1，w2不知道有乜用，代表乜意思。。。<br /></font>#endif<br />/*<br /> * Socket address, internet style.<br /> */<br />struct sockaddr_in {<br />        short   sin_family<font color="#0000ff">;//地址家族一般都是AF_INET或者PF_INET<br /></font>        u_short sin_port<font color="#0000ff">;//端口</font><br />        struct  in_addr sin_addr<font color="#0000ff">;//ip地址<br /></font>        char    sin_zero[8];<br />};<br />/*<br /> * Structure used by kernel to store most<font color="#0000ff">//计算机内核中处理用的是这种表示<br /></font> * addresses.<br /> */<br />struct sockaddr {<br />        u_short sa_family;              /* address family */<br />        char    sa_data[14];            /* up to 14 bytes of direct address */<br />};<br /><font color="#0000ff">//仔细算一下sockaddr_in和sockaddr两个结构的大小是一样，所以可以直接强制类型转换赋值<br />//比如accept函数其中一个参数类型struct sockaddr FAR * ，你如果有一个struct sockaddr_in myaddr<br />//就可以直接accept(..(struct sockaddr *)myaddr.....<br /></font>/*<br /> * WinSock 2 extension -- WSABUF and QOS struct, include qos.h<br /> * to pull in FLOWSPEC and related definitions<br /> */<br />typedef struct _WSABUF <font color="#0000ff">{//缓冲区，一般ms在带WSA前缀的accept，receive，send等函数中才用到<br /></font>    u_long      len;     /* the length of the buffer */<br />    char FAR *  buf;     /* the pointer to the buffer */<br />} WSABUF, FAR * LPWSABUF;<br />typedef struct WSAData {<br />        WORD                    wVersion;<br />        WORD                    wHighVersion;<br />#ifdef _WIN64<br />        unsigned short          iMaxSockets;<br />        unsigned short          iMaxUdpDg;<br />        char FAR *              lpVendorInfo;<br />        char                    szDescription[WSADESCRIPTION_LEN+1];<br />        char                    szSystemStatus[WSASYS_STATUS_LEN+1];<br />#else<br />        char                    szDescription[WSADESCRIPTION_LEN+1];<br />        char                    szSystemStatus[WSASYS_STATUS_LEN+1];<br />        unsigned short          iMaxSockets;<br />        unsigned short          iMaxUdpDg;<br />        char FAR *              lpVendorInfo;<br />#endif<br />} WSADATA, FAR * LPWSADATA<font color="#0000ff">;//其实这个结构不需要怎么了解，因为它在用的很少，就是在调用WSAStartup才用到一次</font></p>
				<p>/*<br /> * Address families.<br /> */<br />#define AF_UNSPEC       0               /* unspecified */<br />/*<br /> * Although  AF_UNSPEC  is  defined for backwards compatibility, using<br /> * AF_UNSPEC for the "af" parameter when creating a socket is STRONGLY<br /> * DISCOURAGED.    The  interpretation  of  the  "protocol"  parameter<br /> * depends  on the actual address family chosen.  As environments grow<br /> * to  include  more  and  more  address families that use overlapping<br /> * protocol  values  there  is  more  and  more  chance of choosing an<br /> * undesired address family when AF_UNSPEC is used.<br /> */<br />#define AF_UNIX         1               /* local to host (pipes, portals) */<br />#define AF_INET         2               /* internetwork: UDP, TCP, etc. */<br />#define AF_IMPLINK      3               /* arpanet imp addresses */<br />#define AF_PUP          4               /* pup protocols: e.g. BSP */<br />#define AF_CHAOS        5               /* mit CHAOS protocols */<br />#define AF_NS           6               /* XEROX NS protocols */<br />#define AF_IPX          AF_NS           /* IPX protocols: IPX, SPX, etc. */<br />#define AF_ISO          7               /* ISO protocols */<br />#define AF_OSI          AF_ISO          /* OSI is ISO */<br />#define AF_ECMA         8               /* european computer manufacturers */<br />#define AF_DATAKIT      9               /* datakit protocols */<br />#define AF_CCITT        10              /* CCITT protocols, X.25 etc */<br />#define AF_SNA          11              /* IBM SNA */<br />#define AF_DECnet       12              /* DECnet */<br />#define AF_DLI          13              /* Direct data link interface */<br />#define AF_LAT          14              /* LAT */<br />#define AF_HYLINK       15              /* NSC Hyperchannel */<br />#define AF_APPLETALK    16              /* AppleTalk */<br />#define AF_NETBIOS      17              /* NetBios-style addresses */<br />#define AF_VOICEVIEW    18              /* VoiceView */<br />#define AF_FIREFOX      19              /* Protocols from Firefox */<br />#define AF_UNKNOWN1     20              /* Somebody is using this! */<br />#define AF_BAN          21              /* Banyan */<br />#define AF_ATM          22              /* Native ATM Services */<br />#define AF_INET6        23              /* Internetwork Version 6 */<br />#define AF_CLUSTER      24              /* Microsoft Wolfpack */<br />#define AF_12844        25              /* IEEE 1284.4 WG AF */<br />#define AF_IRDA         26              /* IrDA */<br />#define AF_NETDES       28              /* Network Designers OSI &amp; gateway<br />                                           enabled protocols */<br />#define AF_TCNPROCESS   29<br />#define AF_TCNMESSAGE   30<br />#define AF_ICLFXBM      31</p>
				<p>#define AF_MAX          32</p>
				<p>/*<br /> * Protocol families, same as address families for now.<br /> */<br />#define PF_UNSPEC       AF_UNSPEC<br />#define PF_UNIX         AF_UNIX<br />#define PF_INET         AF_INET<br />#define PF_IMPLINK      AF_IMPLINK<br />#define PF_PUP          AF_PUP<br />#define PF_CHAOS        AF_CHAOS<br />#define PF_NS           AF_NS<br />#define PF_IPX          AF_IPX<br />#define PF_ISO          AF_ISO<br />#define PF_OSI          AF_OSI<br />#define PF_ECMA         AF_ECMA<br />#define PF_DATAKIT      AF_DATAKIT<br />#define PF_CCITT        AF_CCITT<br />#define PF_SNA          AF_SNA<br />#define PF_DECnet       AF_DECnet<br />#define PF_DLI          AF_DLI<br />#define PF_LAT          AF_LAT<br />#define PF_HYLINK       AF_HYLINK<br />#define PF_APPLETALK    AF_APPLETALK<br />#define PF_VOICEVIEW    AF_VOICEVIEW<br />#define PF_FIREFOX      AF_FIREFOX<br />#define PF_UNKNOWN1     AF_UNKNOWN1<br />#define PF_BAN          AF_BAN<br />#define PF_ATM          AF_ATM<br />#define PF_INET6        AF_INET6</p>
				<p>#define PF_MAX          AF_MAX</p>
				<p>
						<br />下面这些函数属于基本常用函数，下次学习<br />u_long htonl(u_long hostlong)<br />u_short htons(u_short hostshort)<br />u_long ntohl(u_long netlong)<br />u_short ntohs(u_short netshort)<br />unsigned long inet_addr(const char* cp);<br />int getpeername(SOCKET s,struct sockaddr* name,int* namelen);<br />int getsockname(SOCKET s,struct sockaddr* name,int* namelen);<br />char* FAR inet_ntoa(struct in_addr in);<br />struct HOSTENT* FAR gethostbyaddr(const char* addr,int len,int type);<br />struct hostent* FAR gethostbyname(const char* name);<br />int gethostname(char* name,int namelen);<br />int WSAGetLastError(void);<br />int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);<br />int ioctlsocket(SOCKET s,long cmd,u_long* argp);<br />int listen(SOCKET s,int backlog);<br />SOCKET accept(SOCKET s,struct sockaddr* addr,int* addrlen);<br />int send(SOCKET s,const char* buf,int len,int flags);<br />int recv(SOCKET s,char* buf,int len,int flags);</p>
				<p>
				</p>
				<br />
				<br />
				<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=541158</p>
		</div>
<img src ="http://www.cppblog.com/tx7do/aggbug/5956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:28 <a href="http://www.cppblog.com/tx7do/articles/5956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Socket学习笔记之二（常用基本函数） </title><link>http://www.cppblog.com/tx7do/articles/5955.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:27:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5955.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5955.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5955.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5955.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5955.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<p>函数：<br /><font color="#ff6600">u_long htonl(u_long hostlong)<br />u_short htons(u_short hostshort)<br />u_long ntohl(u_long netlong)<br />u_short ntohs(u_short netshort)</font><br />这上面四个函数类似，功能相似，都用来转换数据格式。用来实现处理器中short，long数据类型与网络中的转换。在网络中传输均以字节为单位（除了bit外就是最小的单位了）。一个short占两字节，一个long占四个字节。一个short从一台机子传到另外一台机子上要能够还原，则必须统一规定高低字节顺序。在TCP/IP协议规范中short的高位在低字节，低位在高字节。这与有些处理器中或者系统中表示不一样。例如在windows中：<br /> unsigned short hs = 0x0102;<br /> unsigned short ns = htons( hs );<br /> printf( "0x%04x",ns);//ns:0x0201<br />所以对于网络端口等数据在使用前必须进行统一，例如<br />unsigned short port = 2088；<br />m_sockaddr.sin_port = htons( port );<br />等等。这四个函数，我开始不知道为什么取这些名字总是记不住，后来想明白了<br />htons表示host to net short，ntohs表示net to host short<br />htonl表示host to net long，ntohl表示net to host long<br />这样不需要刻意去记也就明白了。</p>
				<p>
						<font color="#ff6600">unsigned long inet_addr(const char* cp);<br />char* FAR inet_ntoa(struct in_addr in);</font>
						<br />这两个函数用来把表示ip地址的字符串（如：202.114.14.12）跟表示ip的long或者结构之间转换。<br />inet_addr得到的是已经统一字节顺序的，可以直接赋值给in_addr里的s_adr，例如：<br /> char *pHost = "202.114.14.12"<br /> m_sockaddr.sin_addr.s_addr = inet_addr( pHost );</p>
				<p>
						<font color="#ff6600">int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);</font>
						<br />加载winsock库。返回0表示成功，非0表示错误。第一个参数是版本号，现在最高版本是2.2版，不过Win CE好像只支持1.1版，高位字节表示副版本号，低位字节表示高版本号，所以这里一般就是0x0202或者0x0101或者使用宏定义MAKEWORD(2,2)或者MAKEWORD(1,1)，第二个参数是一个与winsock库信息有关的结构，一把不用去管它。在使用winsock前，都必须加载，一般在程序初始化时候做这个事情。一般使用如下：<br /> WSADATA data;<br /> if ( WSAStartup(0x0202,&amp;data) != 0 )<br /> {<br />  printf("error id: %d",GetLastError());<br /> }<br />上面的<font color="#ff6600">GetLastError()</font>是使用非常频繁的函数。很多函数的返回值得意义都是表示函数执行是否出错。当winsock的函数发生错误时，用GetLastError()可以得到最后一次发生错误的错误号。在.Net中有个工具：查找错误，输入错误号，得到错误信息。</p>
				<p>
						<font color="#ff6600">int gethostname(char* name,int namelen);</font>
						<br />获取主机名。输入参数为缓冲区地址和大小。<br /><font color="#ff6600">struct hostent* FAR gethostbyname(const char* name);</font><br />由主机名得到主机信息，可以用来解析域名。需要注意的是MSDN中的一段话“The application must never attempt to modify this structure or to free any of its components. Furthermore, only one copy of this structure is allocated per thread, so the application should copy any information it needs before issuing any other Windows Sockets function calls”这说明了一般用法的时候，要把数据拷贝出来，看看下面代码：<br /> char   name[255];<br /> PHOSTENT  phostinfo;<br /> PHOSTENT  phostinfo1;<br /> WSADATA data;<br /> struct in_addr** addrPtr;<br /> struct in_addr** addrPtr1;</p>
				<p> if ( WSAStartup(0x0202,&amp;data) != 0 )<br /> {<br />  printf("error id: %d",GetLastError());<br /> }</p>
				<p> if( gethostname ( name, sizeof(name)) == 0)<br /> {<br />  printf("%s",name);<br />  if((phostinfo = gethostbyname(name)) != NULL)<br />  {<br />   for (addrPtr = (struct in_addr **)phostinfo-&gt;h_addr_list;*addrPtr;addrPtr++)<br />   {//<font color="#0000ff">显示我机子的ip</font><br />    printf("%s\n", inet_ntoa(**addrPtr));<br />   }<br />  }<br />  else<br />   printf("error id : %d",GetLastError());<br /> }<br /> else<br /> {<br />  printf("error id :%d",GetLastError());<br /> }</p>
				<p> if((phostinfo1 = gethostbyname("bbs.whnet.edu.cn")) != NULL)<br /> {<br />  for (addrPtr1 = (struct in_addr **)phostinfo-&gt;h_addr_list;*addrPtr1;addrPtr1++)<br />  <font color="#0000ff">{//显示bbs.whnet.edu.cn的ip：202.114.0.248<br /></font>   printf("%s\n", inet_ntoa(**addrPtr1));<br />  }<br /> }<br /> else<br />  printf("error id : %d",GetLastError());</p>
				<p> for (addrPtr = (struct in_addr **)phostinfo-&gt;h_addr_list;*addrPtr;addrPtr++)<br /> <font color="#0000ff">{//在这里显示的是bbs.whnet.edu.cn的ip：202.114.0.248，不是我机子的ip<br /></font>  printf("%s\n", inet_ntoa(**addrPtr));<br /> }</p>
				<p>
						<font color="#ff6600">struct HOSTENT* FAR gethostbyaddr(const char* addr,int len,int type);<br /></font>根据ip地址得到主机信息。这里的ip必须是网络字节顺序的。示例代码：<br /> PHOSTENT phostinfo2;<br /> unsigned long ip = inet_addr("127.0.0.1");<br /> if ( (phostinfo2 = gethostbyaddr((char*)&amp;ip,sizeof(ip),AF_INET)) != NULL)<br /> {//显示localhost<br />  printf("host name : %s",phostinfo2-&gt;h_name );<br /> }<br /> else<br />  printf("error id : %d",GetLastError());</p>
				<p>
						<font color="#ff6600">int getsockname(SOCKET s,struct sockaddr* name,int* namelen);</font>
						<br />这个函数用来的得到socket的本地地址，但是前提是socket必须已经bind或者已经是连接上的。如果socket不是面向连接的话，比如udp，那得socket上有数据才行。<br /><font color="#ff6600">int getpeername(SOCKET s,struct sockaddr* name,int* namelen);</font><br />这个函数用来得到socket那一边上的地址，显然socket必须得连接上。“The getpeername function can be used only on a connected socket. For datagram sockets, only the name of a peer specified in a previous connect call will be returned—any name specified by a previous sendto call will not be returned by getpeername.”</p>
				<p>至于bind,listen,accept,recv,send等后面学select模型的时候再仔细研究。</p>
				<br />
				<br />
				<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=551760</p>
		</div>
<img src ="http://www.cppblog.com/tx7do/aggbug/5955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:27 <a href="http://www.cppblog.com/tx7do/articles/5955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows I/O模型、同步/异步、阻塞/非阻塞</title><link>http://www.cppblog.com/tx7do/articles/5954.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:25:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5954.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5954.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5954.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5954.html</trackback:ping><description><![CDATA[<span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium/26px arial, sans-serif, 宋体; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class=Apple-style-span><span style="LINE-HEIGHT: 22px; FONT-SIZE: 14px" class=Apple-style-span>
<p style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体"><strong><span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium/26px arial, sans-serif, 宋体; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class=Apple-style-span><span style="LINE-HEIGHT: 22px; FONT-SIZE: 14px" class=Apple-style-span><strong style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">同步</strong><br style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">　　所谓同步，就是在发出一个功能调用时，在没有得到结果之前，该调用就不返回。按照这个定义，其实绝大多数函数都是同步调用（例如sin, isdigit等）。但是一般而言，我们在说同步、异步的时候，特指那些需要其他部件协作或者需要一定时间完成的任务。最常见的例子就是 SendMessage。该函数发送一个消息给某个窗口，在对方处理完消息之前，这个函数不返回。当对方处理完毕以后，该函数才把消息处理函数所返回的 LRESULT值返回给调用者。</span></span></strong></p>
<p><span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium/26px arial, sans-serif, 宋体; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class=Apple-style-span><span style="LINE-HEIGHT: 22px; FONT-SIZE: 14px" class=Apple-style-span><strong style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">异步</strong><br style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">　　异步的概念和同步相对。当一个异步过程调用发出后，调用者不能立刻得到结果。实际处理这个调用的部件在完成后，通过状态、通知和回调来通知调用者。以 CAsycSocket类为例（注意，CSocket从CAsyncSocket派生，但是起功能已经由异步转化为同步），当一个客户端通过调用 Connect函数发出一个连接请求后，调用者线程立刻可以朝下运行。当连接真正建立起来以后，socket底层会发送一个消息通知该对象。这里提到执行 部件和调用者通过三种途径返回结果：状态、通知和回调。可以使用哪一种依赖于执行部件的实现，除非执行部件提供多种选择，否则不受调用者控制。如果执行部 件用状态来通知，那么调用者就需要每隔一定时间检查一次，效率就很低（有些初学多线程编程的人，总喜欢用一个循环去检查某个变量的值，这其实是一种很严重 的错误）。如果是使用通知的方式，效率则很高，因为执行部件几乎不需要做额外的操作。至于回调函数，其实和通知没太多区别。<br><span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium/26px arial, sans-serif, 宋体; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class=Apple-style-span><span style="LINE-HEIGHT: 22px; FONT-SIZE: 14px" class=Apple-style-span><strong style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体"><br>阻塞</strong><br style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">　　阻塞调用是指调用结果返回之前，当前线程会被挂起。函数只有在得到结果之后才会返回。有人也许会把阻塞调用和同步调用等同起来，实际上他是不同的。对于同 步调用来说，很多时候当前线程还是激活的，只是从逻辑上当前函数没有返回而已。例如，我们在CSocket中调用Receive函数，如果缓冲区中没有数 据，这个函数就会一直等待，直到有数据才返回。而此时，当前线程还会继续处理各种各样的消息。如果主窗口和调用函数在同一个线程中，除非你在特殊的界面操 作函数中调用，其实主界面还是应该可以刷新。socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候， 如果没有数据的情况下调用该函数，则当前线程就会被挂起，直到有数据为止。</p>
<p style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体"><strong style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">非阻塞</strong><br style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">　　非阻塞和阻塞的概念相对应，指在不能立刻得到结果之前，该函数不会阻塞当前线程，而会立刻返回。</p>
<p style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">　　对象的阻塞模式和阻塞函数调用<br style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">　　对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性，但是并不是一一对应的。阻塞对象上可以有非阻塞的调用方式，我们可以通过一定的API去轮询状 态，在适当的时候调用阻塞函数，就可以避免阻塞。而对于非阻塞对象，调用特殊的函数也可以进入阻塞调用。函数select就是这样的一个例子。</p>
<p></span></span></span></span></span></span><br>在Winsock中实现异步的方法有很多，Winsock的IO模型有下面六种<br><strong>&nbsp;&nbsp;&nbsp; 一：select模型<br>&nbsp;&nbsp;&nbsp; 二：WSAAsyncSelect模型<br>&nbsp;&nbsp;&nbsp; 三：WSAEventSelect模型<br>&nbsp;&nbsp;&nbsp; 四：Overlapped I/O 事件通知模型<br>&nbsp;&nbsp;&nbsp; 五：Overlapped I/O 完成例程模型<br>&nbsp;&nbsp;&nbsp; 六：IOCP模型</strong><br>从一到六越来越高级，越来越高效，实现越来越复杂。<br><br><br>曾在网上看到一些比喻用来很好的说明这些模型，在这里引用一下。<br>老陈有一个在外地工作的女儿，不能经常回来，老陈和她通过信件联系。他们的信会被邮递员投递到他们的信箱里。<br><strong>一：select模型</strong></p>
<p>老陈非常想看到女儿的信。以至于他每隔10分钟就下楼检查信箱，看是否有女儿的信~~~~~<br>在这种情况下，&#8220;下楼检查信箱&#8221;然后回到楼上耽误了老陈太多的时间，以至于老陈无法做其他工作。</p>
<p><strong>二：WSAAsyncSelect模型</strong></p>
<p>后来，老陈使用了微软公司的新式信箱。这种信箱非常先进，一旦信箱里有新的信件，盖茨就会给老陈打电话：喂，大爷，你有新的信件了！从此，老陈再也不必频繁上下楼检查信箱了，牙也不疼了，你瞅准了，蓝天......不是，微软~~~~~~~~</p>
<p><strong>三：WSAEventSelect模型</strong></p>
<p>后来，微软的信箱非常畅销，购买微软信箱的人以百万计数......以至于盖茨每天24小时给客户打电话，累得腰酸背痛，喝蚁力神都不好使~~~~~~<br>微软改进了他们的信箱：在客户的家中添加一个附加装置，这个装置会监视客户的信箱，每当新的信件来临，此装置会发出&#8220;新信件到达&#8221;声，提醒老陈去收信。盖茨终于可以睡觉了。</p>
<p><strong>四：Overlapped I/O 事件通知模型</strong></p>
<p>后来，微软通过调查发现，老陈不喜欢上下楼收发信件，因为上下楼其实很浪费时间。于是微软再次改进他们的信箱。新式的信箱采用了更为先进的技术，只要用户告诉微软自己的家在几楼几号，新式信箱会把信件直接传送到用户的家中，然后告诉用户，你的信件已经放到你的家中了！老陈很高兴，因为他不必再亲自收发信件了！</p>
<p><strong>五：Overlapped I/O 完成例程模型</strong></p>
<p>老陈接收到新的信件后，一般的程序是：打开信封----掏出信纸----阅读信件----回复信件......为了进一步减轻用户负担，微软又开发了一种新的技术：用户只要告诉微软对信件的操作步骤，微软信箱将按照这些步骤去处理信件，不再需要用户亲自拆信/阅读/回复了！老陈终于过上了小资生活！</p>
<p><strong>六：IOCP模型</strong></p>
<p>微软信箱似乎很完美，老陈也很满意。但是在一些大公司情况却完全不同！这些大公司有数以万计的信箱，每秒钟都有数以百计的信件需要处理，以至于微软信箱经常因超负荷运转而崩溃！需要重新启动！微软不得不使出杀手锏......<br>微软给每个大公司派了一名名叫&#8220;Completion Port&#8221;的超级机器人，让这个机器人去处理那些信件！</p>
<p><br>其实，上面每种模型都有优点，要根据程序需求而适当选择合适的模型，前面三种模型效率已经比较高，实现起来难道不大，很多一般的网络程序都采用前三种模型，只有对网络要求特别高的一些服务器才会考虑用后面的那些模型。MFC中的CAsyncSocket类就是用的WSAAsyncSelect模型，电驴中也是用的这种，不过在寻找对应socket的时候进行了优化，查找更快，在GridCast中采用的是WSAEventSelect模型，等待。</p>
<img src ="http://www.cppblog.com/tx7do/aggbug/5954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:25 <a href="http://www.cppblog.com/tx7do/articles/5954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何编写Linux下的客户机/服务器软件</title><link>http://www.cppblog.com/tx7do/articles/5952.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:19:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5952.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5952.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5952.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5952.html</trackback:ping><description><![CDATA[　　 Linux以其源代码公开闻名于世，并以其稳定性和可靠性雄霸操作系统领域，在网络应用技术方面使用得更加广泛。很久以来它就是Windows的重要对手之一。随着网络时代的来临，Linux的这种优势已变得更加突出。本文将论述如何在Linux环境下利用Socket实现客户机/服务器通信。 <br />随着网络技术的发展，网络结构已从过去的主机/终端型、对等型发展到现在广为使用的客户机/服务器型。客户机/服务器模型应用十分广泛，在Internet上WWW，E-mail，FTP等都是基于这种模型的。在面向连接的通信模式下，服务器打开监听端口，监听网络上其它客户机向该服务器发出的连接请求，当收到一个请求信号时与该客户机建立一个连接，之后两者进行交互式的通信。具体步骤可这样组织： <br /><br />服务器： <br />1.打开一个已知的监听端口，如smtp为25、pop3为110、ftp为21、telnet为23等。 <br />2.在监听端口上监听客户机的连接请求，如果有客户机请求连接则建立一个连接线路。 <br />3.在连接线路上与客户机通信。 <br />4.通信完毕后关闭连接线路并继续监听客户机的连接请求。 <br /><br />客户机： <br />1.向指定的服务器主机及端口发出连接请求。 <br />2.当服务器建立连接线路后与服务器进行通信。 <br />3.通信完毕后关闭连接线路。 <br /><br />Linux的许多特性都非常有助于网络程序设计：首先Linux拥有POSIX.1标准库函数，socket()、bind()、listen()这几个库函数可以非常方便地实现服务器/客户机模型，有关这几个库函数的使用说明将在后边介绍。其次Linux的进程管理也非常符合服务器的工作原理，所谓进程就是程序在内存中运行时的状态，可以说进程是动态的程序。在运行着Linux操作系统的计算机中，每一个进程都有一个创建它的父进程，而且它也能创建多个子进程。在服务器端我们可以用父进程去监听客户机的连接请求，当有客户机的连接请求时父进程创建一个子进程去建立连接线路并与客户机通信，而它本身可继续监听其它客户机的连接请求，这样就可避免当有一个客户机与服务器建立连接后服务器就不能再与其它客户机通信的问题。Linux的另一个特性是它秉承了UNIX设备无关性这一优秀特征，即它通过文件描述符实现了统一的设备接口，磁盘、显示终端、音频设备、打印设备甚至网络通信都使用统一的I/O调用。这三个特性将使Linux下的网络程序设计变得易如反掌。上述三个特性的综合利用将是这篇文章所要讲述的真谛所在。下边的客户机/服务器实现过程可以说明一二，注意与上文所述步骤的不同。 <br /><br />服务器： <br />1.打开一个已知的监听端口。 <br />2.在监听端口上监听客户机的连接请求，当有一客户机请求连接时建立连接线路并返回通信文件描述符。 <br />4.父进程创建一子进程，父进程关闭通信文件描述符并继续监听端口上的客户机连接请求。 <br />3.子进程通过通信文件描述符与客户机进行通信，通信结束后终止子进程并关闭通信文件描述符。 <br /><br />客户机： <br />1.向指定的服务器主机及端口发出连接请求，请求成功将返回通信文件描述符。 <br />2.通过通信文件描述符与服务器进行通信。 <br />3.通信完毕后关闭通信文件描述符。 <br /><br /><br />Linux的以下几个库函数是网络程序设计的核心部分，它们分别是： <br />(1)socket <br />调用方式： <br />#include <br />#include <br /><br />int socket(int domain,int type,int protocol); <br /><br />简要说明： <br />此函数为通信创建一个端口，正常调用将返回一个文件描述符，错误调用将返回-1。domain参数有两种选择：AF_UNIX与AF_INET，其中AF_INET为Internet通信协议。type参数也有两种选择：SOCK_STREAM用于TCP，SOCK_DGRAM用于UDP。protocol参数通常为0。可通过下列代码为基于TCP协议的Internet通信建立套接口传输端口： <br /><br />#include <br />#include <br />#include <br />int sock; <br /><br />if((sock=socket(AF_INET,SOCK_STREAM,0))==-1) <br />perror("Could not create socket"); <br /><br />(2)bind <br />调用方式： <br />#include <br />#include <br /><br />int bind(int s,const struct sockaddr *address,size_t address_len); <br /><br />简要说明： <br />bind英文含意是关联，捆绑。其目的就是把socket返回的套接口端口与网络上的物理位置相关联。 <br />bind正常调用返回0，出错返回-1。此函数有三个参数：其中s为socket调用返回的文件描述符，*address设置了与网络上的物理位置相关的信息，它的类型是struct sockaddr，但在Internet上它是struct sockaddr_in。在socket.h中struct sockaddr_in定义为： <br />struct sockaddr_in{ <br />short sin_family; <br />u_short sin_port; <br />struct in_addr sin_addr; <br />char sin_zero[8]; <br />}; <br />sin_family一般为AF_INET，sin_port为端口号，由于使用不同字节顺序的机器必须作转换，故应使用宏命令htons(host to network short)来转换端口号，sin_addr将置为INADDR_ANY。这三个值设置完成后*address参数才有意义。在编写代码时，应先设置*address参数内部各成员变量的值，再调用bind。 <br /><br />(3)listen <br />调用方式： <br />#include <br />#include <br /><br />int listen(int s,int backlog); <br /><br />简要说明： <br />本函数使socket端口能够接受从客户机来的连接请求，正常调用返回0，出错返回-1。 <br />s参数为socket产生的文件描述符，backlog为所能接受客户机的最大数目。 <br />socket，bind，listen 三个函数的综合调用最终在服务器上产生一个能接受客户机请求的监听文件描述符s。 <br /><br />(4)accept <br />调用方式： <br />#include <br />#include <br /><br />int accept(int s,struct sockaddr *address,int *address_len); <br /><br />简要说明： <br />当有客户机发出连接请求时，此函数初始化这个连接。正常调用返回与客户机通信的通信文件描述符，出错返回-1。参数s为socket调用返回的文件描述符，address将用来存储客户机的信息，此信息由accept填入，当与客户机连接时，客户机的地址与端口将填到此处。address_len是客户机地址长度的字节数，也由accept填入。 <br /><br />(5)connect <br />调用方式： <br />#include <br />#include <br /><br />int connect(int s,struct sockaddr *address,size_t address_len); <br /><br />简要说明： <br />客户机调用socket建立传输端口后，调用connect来建立与远程服务器相连的连接线路。 <br />此函数的参数调用同bind。 <br /><br />(6)inet_addr <br />调用方式： <br />#include <br />#include <br />#include <br /><br />in_addr_t inet_addr(const char *addstring); <br /><br />简要说明： <br />此函数将字符串addstring表示的网络地址（如192.168.0.1）转换成32位的网络字节序二进制值，若成功返回32位二进制的网络字节序地址，若出错返回 INADDR_NONE。INADDR_NONE是32位均为1的值（即255.255.255.255，它是Internet的有限广播地址），故如果要转换的addstring是255.255.255.255，函数调用将失败。 <br /><br />(7)fork <br />调用方式： <br />#include <br />#include <br /><br /><br />pid_t fork(void); <br /><br />简要说明： <br />fork的作用是拷贝父进程的内存映象来创建子进程，两个进程将接着fork后的指令继续执行。 事实上它返回两个进程控制号，对于父进程它返回子进程的进程ID，对于子进程它返回0。 <br /><br />可用下边的代码调用fork： <br /><br />pid_t childpid; <br />if((childpid=fork())=-1){ <br />perror("The fork failed"); <br />exit(1); <br />} <br />else if(child==0){ <br />调用子进程; <br />} <br />else if(child&gt;0){ <br />调用父进程; <br />} <br /><br /><br />以上介绍了网络编程的有关库函数的调用方法，下面举一个客户机/服务器程序的小例子具体说明如何设计网络程序。本例介绍如何查看服务器上的时间和日期，由于daytime服务器的通用端口为13，客户机程序将通过调用13号端口对服务器上的时间和日期进行操作。 <br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Codehighlighter1_0_14_Open_Image" onclick="this.style.display='none'; Codehighlighter1_0_14_Open_Text.style.display='none'; Codehighlighter1_0_14_Closed_Image.style.display='inline'; Codehighlighter1_0_14_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_0_14_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_0_14_Closed_Text.style.display='none'; Codehighlighter1_0_14_Open_Image.style.display='inline'; Codehighlighter1_0_14_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span id="Codehighlighter1_0_14_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_0_14_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">timeserve.c</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"> <br /><img id="Codehighlighter1_17_165_Open_Image" onclick="this.style.display='none'; Codehighlighter1_17_165_Open_Text.style.display='none'; Codehighlighter1_17_165_Closed_Image.style.display='inline'; Codehighlighter1_17_165_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_17_165_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_17_165_Closed_Text.style.display='none'; Codehighlighter1_17_165_Open_Image.style.display='inline'; Codehighlighter1_17_165_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_17_165_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_17_165_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">服务器程序伪代码如下： <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />打开daytime监听端口； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />while(客户机与服务器成功连接——成功返回通信文件描述符) <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />fork() <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />子进程： <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />读出当前时间； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />将当前时间写入通信文件描述符； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />关闭通信文件描述符； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />} <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />父进程： <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />关闭通信文件描述符； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />} <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /></span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> argc,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">argv[]) <br /><img id="Codehighlighter1_343_1167_Open_Image" onclick="this.style.display='none'; Codehighlighter1_343_1167_Open_Text.style.display='none'; Codehighlighter1_343_1167_Closed_Image.style.display='inline'; Codehighlighter1_343_1167_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_343_1167_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_343_1167_Closed_Text.style.display='none'; Codehighlighter1_343_1167_Open_Image.style.display='inline'; Codehighlighter1_343_1167_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_343_1167_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_343_1167_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> listenfd,communfd; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr_in servaddr; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />pid_t childpid; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />time_t tick; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> buf[</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">]; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((listenfd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">socket(AF_INET,SOCK_STREAM,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">))</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_499_548_Open_Image" onclick="this.style.display='none'; Codehighlighter1_499_548_Open_Text.style.display='none'; Codehighlighter1_499_548_Closed_Image.style.display='inline'; Codehighlighter1_499_548_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_499_548_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_499_548_Closed_Text.style.display='none'; Codehighlighter1_499_548_Open_Image.style.display='inline'; Codehighlighter1_499_548_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_499_548_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_499_548_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Could not create socket</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />servaddr.sin_family</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">AF_INET; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />servaddr.sin_addr.s_addr</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">INADDR_ANY; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />servaddr.sin_port</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">htons(</span><span style="COLOR: #000000">13</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(bind(listenfd,(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">servaddr,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(servaddr))</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_720_756_Open_Image" onclick="this.style.display='none'; Codehighlighter1_720_756_Open_Text.style.display='none'; Codehighlighter1_720_756_Closed_Image.style.display='inline'; Codehighlighter1_720_756_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_720_756_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_720_756_Closed_Text.style.display='none'; Codehighlighter1_720_756_Open_Image.style.display='inline'; Codehighlighter1_720_756_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_720_756_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_720_756_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">bind error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(listen(listenfd,</span><span style="COLOR: #000000">254</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_789_827_Open_Image" onclick="this.style.display='none'; Codehighlighter1_789_827_Open_Text.style.display='none'; Codehighlighter1_789_827_Closed_Image.style.display='inline'; Codehighlighter1_789_827_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_789_827_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_789_827_Closed_Text.style.display='none'; Codehighlighter1_789_827_Open_Image.style.display='inline'; Codehighlighter1_789_827_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_789_827_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_789_827_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">listen error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(communfd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">accept(listenfd,(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)NULL,NULL)) <br /><img id="Codehighlighter1_892_1154_Open_Image" onclick="this.style.display='none'; Codehighlighter1_892_1154_Open_Text.style.display='none'; Codehighlighter1_892_1154_Closed_Image.style.display='inline'; Codehighlighter1_892_1154_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_892_1154_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_892_1154_Closed_Text.style.display='none'; Codehighlighter1_892_1154_Open_Image.style.display='inline'; Codehighlighter1_892_1154_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_892_1154_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_892_1154_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((childpid</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fork())</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_922_958_Open_Image" onclick="this.style.display='none'; Codehighlighter1_922_958_Open_Text.style.display='none'; Codehighlighter1_922_958_Closed_Image.style.display='inline'; Codehighlighter1_922_958_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_922_958_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_922_958_Closed_Text.style.display='none'; Codehighlighter1_922_958_Open_Image.style.display='inline'; Codehighlighter1_922_958_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_922_958_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_922_958_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">fork error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(childpid</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_983_1111_Open_Image" onclick="this.style.display='none'; Codehighlighter1_983_1111_Open_Text.style.display='none'; Codehighlighter1_983_1111_Closed_Image.style.display='inline'; Codehighlighter1_983_1111_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_983_1111_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_983_1111_Closed_Text.style.display='none'; Codehighlighter1_983_1111_Open_Image.style.display='inline'; Codehighlighter1_983_1111_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_983_1111_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_983_1111_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />tick</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">time(NULL); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />snprintf(buf,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(buf),</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%.24s\r\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,ctime(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">tick)); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />write(communfd,buf,strlen(buf)); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />close(communfd); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(childpid</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">) <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />close(communfd); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_1172_1187_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1172_1187_Open_Text.style.display='none'; Codehighlighter1_1172_1187_Closed_Image.style.display='inline'; Codehighlighter1_1172_1187_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_1172_1187_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1172_1187_Closed_Text.style.display='none'; Codehighlighter1_1172_1187_Open_Image.style.display='inline'; Codehighlighter1_1172_1187_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_1172_1187_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_1172_1187_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">timeclient.h</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> argc,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">argv[]) <br /><img id="Codehighlighter1_1314_1972_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1314_1972_Open_Text.style.display='none'; Codehighlighter1_1314_1972_Closed_Image.style.display='inline'; Codehighlighter1_1314_1972_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_1314_1972_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1314_1972_Closed_Text.style.display='none'; Codehighlighter1_1314_1972_Open_Image.style.display='inline'; Codehighlighter1_1314_1972_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_1314_1972_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1314_1972_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> communfd,n; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr_in servaddr; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> recieve[</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">],buf[</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">]; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(argc</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_1409_1449_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1409_1449_Open_Text.style.display='none'; Codehighlighter1_1409_1449_Closed_Image.style.display='inline'; Codehighlighter1_1409_1449_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1409_1449_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1409_1449_Closed_Text.style.display='none'; Codehighlighter1_1409_1449_Open_Image.style.display='inline'; Codehighlighter1_1409_1449_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_1409_1449_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1409_1449_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Usage: client </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((communfd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">socket(AF_INET,SOCK_STREAM,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">))</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_1502_1540_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1502_1540_Open_Text.style.display='none'; Codehighlighter1_1502_1540_Closed_Image.style.display='inline'; Codehighlighter1_1502_1540_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1502_1540_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1502_1540_Closed_Text.style.display='none'; Codehighlighter1_1502_1540_Open_Image.style.display='inline'; Codehighlighter1_1502_1540_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_1502_1540_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1502_1540_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">socket error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />servaddr.sin_family</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">AF_INET; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />servaddr.sin_port</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">htons(</span><span style="COLOR: #000000">13</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((servaddr.sin_addr.s_addr</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">inet_addr(argv[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]))</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">INADDR_NONE) <br /><img id="Codehighlighter1_1667_1708_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1667_1708_Open_Text.style.display='none'; Codehighlighter1_1667_1708_Closed_Image.style.display='inline'; Codehighlighter1_1667_1708_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1667_1708_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1667_1708_Closed_Text.style.display='none'; Codehighlighter1_1667_1708_Open_Image.style.display='inline'; Codehighlighter1_1667_1708_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_1667_1708_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1667_1708_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">inet_addr error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(connect(communfd,(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">servaddr,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(servaddr))</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_1783_1822_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1783_1822_Open_Text.style.display='none'; Codehighlighter1_1783_1822_Closed_Image.style.display='inline'; Codehighlighter1_1783_1822_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1783_1822_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1783_1822_Closed_Text.style.display='none'; Codehighlighter1_1783_1822_Open_Image.style.display='inline'; Codehighlighter1_1783_1822_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_1783_1822_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1783_1822_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">connect error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">((n</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">read(communfd,recieve,</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">))</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">) <br /><img id="Codehighlighter1_1867_1941_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1867_1941_Open_Text.style.display='none'; Codehighlighter1_1867_1941_Closed_Image.style.display='inline'; Codehighlighter1_1867_1941_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1867_1941_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1867_1941_Closed_Text.style.display='none'; Codehighlighter1_1867_1941_Open_Image.style.display='inline'; Codehighlighter1_1867_1941_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="Codehighlighter1_1867_1941_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1867_1941_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />recieve[n]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(fputs(recieve,stdout)</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">EOF) <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">fputs error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />close(communfd); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span></div>用gcc编译两个源程序分别取名为server和client，以根用户身份运行服务器程序（设服务器网络地址为192.168.0.1）： <br />server &amp; <br />然后运行客户机程序（设服务器网络地址为192.168.0.1）： <br />client 192.168.0.1 <br />在客户机上就会反映出服务器上当前的时间如（Tue Feb 29 21:46:19 2000）。 <br /><br />以上程序代码在redhat 6.0上试验通过。在程序代码中有关库函数snprintf、fputs、read、write、close的用法就不在这里说明了，如想了解这些库函数的调用方法可到我的网页http://lzdx.yeah. net/pro_unix.html去查找。在我的网页http://lzdx.yeah.net/pro_uici.html中有关于通用Internet接口（UICI）专用库的介绍，通用Internet接口（UICI）利用Socket库函数提供了一个简化的独立于传输的接口，它从整体上简化了网络程序设计过程。有兴趣的人可到那里去看看。最后祝愿我们每个人都能编写出自己的网络程序。<img src ="http://www.cppblog.com/tx7do/aggbug/5952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:19 <a href="http://www.cppblog.com/tx7do/articles/5952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>unix下编写socket程序的一般步骤</title><link>http://www.cppblog.com/tx7do/articles/5951.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:17:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5951.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5951.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5951.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5951.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5951.html</trackback:ping><description><![CDATA[在unix下写socket程序可能是最方便，你只要掌握其一般步骤，就可以松的写出面向传输层的应用。 <br /><br />　　1、<b>理解几个常用的socket函数</b><br /><br />　　#include <sys types.h=""><br /><br />　　#include <sys socket.h=""><br /><br />　　int socket(int domain,int type,int portocol);<br /><br />　　domain指所使用的协议族(family)可以为AF_UNIX和AF_INET,一般只用AF_INET(指Internet)type指所用的传输类型，可以为SOCK_STERAM(面向连接的TCP),和SOCK_DGRAM(面向无连接的udp)<br /><br />　　int bind(int s,const struct sockaddr *address,size_t address_len);<br /><br />　　s为socket返回的文件描述符<br /><br />　　address为协议族名称和其他信息<br /><br />　　具体结构为struct sockaddr_in{<br /><br />　　　short sin_family;/*协议族<br /><br />　　　u_short sin_port;/*端口*/<br /><br />　　　struct in_addr sin_addr;/*地址*/<br /><br />　　　char sin_zero[8];<br /><br />　　};<br /><br />　　int listen(int s,int backlog);<br /><br />　　<font color="#008000">backlog为容许的请求数目</font><br /><br />　　int accept(int s,struct sockaddr *address,int *address_len);<br /><br />　　<font color="#008000">这里的前两个参数同上</font><br /><br />　　<font color="#008000">addres_len是要传递一个记有结构大小的地址</font><br /><br />　　int connect(int s,struct sockaddr *address,size_t address_len);<br /><br />　　<font color="#004000">这里的参数意义同bind</font><br /><br />　　2.<b>理解建立程序的一般调用过程</b><br /><br />　　要建立一个处理连接的服务器端程序，首先要调用socket函数创建一个socket,返回一个文件句柄fd，使以后对它的操作就象对普通文件设备一样读写。<br /><br />　　由于是服务器端必须对一个断口进行监听其他机器的请求,所以接下去调用bind函数，传入刚才的fd,定义好地址和端口，由于是要接受来自任何host的连接所以应讲sin_addr赋为INADDR_ANY,port为你所设定的端口。<br /><br />　　<b>注意</b>：这里的地址和端口是网络字节顺序，所以要调用htonl,htons完成主机字节顺序<br />到网络字节的转变<br /><br />　　接下来就是监听listen,调用accept接受来自客户端的请求，accpet返回连接后的文件描述符，你就可以用它进行收发信息（对应于read,write)这样的一个过程就是socket-&gt;bind-&gt;listen-&gt;accpet-&gt;Read,write<br />而对于客户端则是socket-&gt;connect-&gt;read,write
<p><span class="txt">3.<b>一个完整的程序</b><br /></span></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">　　#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />　　#include <br /><img id="Codehighlighter1_35_53_Open_Image" onclick="this.style.display='none'; Codehighlighter1_35_53_Open_Text.style.display='none'; Codehighlighter1_35_53_Closed_Image.style.display='inline'; Codehighlighter1_35_53_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_35_53_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_35_53_Closed_Text.style.display='none'; Codehighlighter1_35_53_Open_Image.style.display='inline'; Codehighlighter1_35_53_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" />　　#include </span><span id="Codehighlighter1_35_53_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_35_53_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">包含有htons等函数的头文件</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />　　#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />　　#include <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />　　</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> main()<br /><img id="Codehighlighter1_98_1277_Open_Image" onclick="this.style.display='none'; Codehighlighter1_98_1277_Open_Text.style.display='none'; Codehighlighter1_98_1277_Closed_Image.style.display='inline'; Codehighlighter1_98_1277_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_98_1277_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_98_1277_Closed_Text.style.display='none'; Codehighlighter1_98_1277_Open_Image.style.display='inline'; Codehighlighter1_98_1277_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" />　　　</span><span id="Codehighlighter1_98_1277_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_98_1277_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> listenfd,clifd;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> pid;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr_in myaddr,cliaddr;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> ret;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> len;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　listenfd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">socket(AF_INET,SOCK_STREAM,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (listenfd</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_274_327_Open_Image" onclick="this.style.display='none'; Codehighlighter1_274_327_Open_Text.style.display='none'; Codehighlighter1_274_327_Closed_Image.style.display='inline'; Codehighlighter1_274_327_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_274_327_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_274_327_Closed_Text.style.display='none'; Codehighlighter1_274_327_Open_Image.style.display='inline'; Codehighlighter1_274_327_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　</span><span id="Codehighlighter1_274_327_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_274_327_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">socket error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　exit(</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　　　　}</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　myaddr.sin_family</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">AF_INET;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　myaddr.sin_addr.s_addr</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">htonl(INADDR_ANY);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　myaddr.sin_port</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">htons(</span><span style="COLOR: #000000">8888</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　ret</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">bind(listenfd,(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">myaddr,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(myaddr));<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (ret</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_527_578_Open_Image" onclick="this.style.display='none'; Codehighlighter1_527_578_Open_Text.style.display='none'; Codehighlighter1_527_578_Closed_Image.style.display='inline'; Codehighlighter1_527_578_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_527_578_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_527_578_Closed_Text.style.display='none'; Codehighlighter1_527_578_Open_Image.style.display='inline'; Codehighlighter1_527_578_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　</span><span id="Codehighlighter1_527_578_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_527_578_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">bind error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　exit(</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　　　　}</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　listen(listenfd,</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　len</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_656_1268_Open_Image" onclick="this.style.display='none'; Codehighlighter1_656_1268_Open_Text.style.display='none'; Codehighlighter1_656_1268_Closed_Image.style.display='inline'; Codehighlighter1_656_1268_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_656_1268_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_656_1268_Closed_Text.style.display='none'; Codehighlighter1_656_1268_Open_Image.style.display='inline'; Codehighlighter1_656_1268_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　</span><span id="Codehighlighter1_656_1268_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_656_1268_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　clifd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">accept(listenfd,(</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">cliaddr,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">len);<br /><img id="Codehighlighter1_727_748_Open_Image" onclick="this.style.display='none'; Codehighlighter1_727_748_Open_Text.style.display='none'; Codehighlighter1_727_748_Closed_Image.style.display='inline'; Codehighlighter1_727_748_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_727_748_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_727_748_Closed_Text.style.display='none'; Codehighlighter1_727_748_Open_Image.style.display='inline'; Codehighlighter1_727_748_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　　 </span><span id="Codehighlighter1_727_748_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_727_748_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">注意accept的第三个参数也是地址</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(clifd</span><span style="COLOR: #000000">==-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_777_837_Open_Image" onclick="this.style.display='none'; Codehighlighter1_777_837_Open_Text.style.display='none'; Codehighlighter1_777_837_Closed_Image.style.display='inline'; Codehighlighter1_777_837_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_777_837_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_777_837_Closed_Text.style.display='none'; Codehighlighter1_777_837_Open_Image.style.display='inline'; Codehighlighter1_777_837_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　　　</span><span id="Codehighlighter1_777_837_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_777_837_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">accept error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　</span><span style="COLOR: #0000ff">continue</span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　　　　　　　}</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">connect from %s %d </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port));<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">(pid</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">fork())<br /><img id="Codehighlighter1_968_1259_Open_Image" onclick="this.style.display='none'; Codehighlighter1_968_1259_Open_Text.style.display='none'; Codehighlighter1_968_1259_Closed_Image.style.display='inline'; Codehighlighter1_968_1259_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_968_1259_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_968_1259_Closed_Text.style.display='none'; Codehighlighter1_968_1259_Open_Image.style.display='inline'; Codehighlighter1_968_1259_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　　　</span><span id="Codehighlighter1_968_1259_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_968_1259_Open_Text"><span style="COLOR: #000000">{<br /><img id="Codehighlighter1_986_992_Open_Image" onclick="this.style.display='none'; Codehighlighter1_986_992_Open_Text.style.display='none'; Codehighlighter1_986_992_Closed_Image.style.display='inline'; Codehighlighter1_986_992_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_986_992_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_986_992_Closed_Text.style.display='none'; Codehighlighter1_986_992_Open_Image.style.display='inline'; Codehighlighter1_986_992_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　　　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">: </span><span id="Codehighlighter1_986_992_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_986_992_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">子进程</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　　close(listenfd);<br /><img id="Codehighlighter1_1034_1047_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1034_1047_Open_Text.style.display='none'; Codehighlighter1_1034_1047_Closed_Image.style.display='inline'; Codehighlighter1_1034_1047_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1034_1047_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1034_1047_Closed_Text.style.display='none'; Codehighlighter1_1034_1047_Open_Image.style.display='inline'; Codehighlighter1_1034_1047_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　　　　　　　;</span><span id="Codehighlighter1_1034_1047_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_1034_1047_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">子进程进行其他的操作</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　　close(clifd);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　　exit(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　　</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">:<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　　perror(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">fork error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　　</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br /><img id="Codehighlighter1_1199_1205_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1199_1205_Open_Text.style.display='none'; Codehighlighter1_1199_1205_Closed_Image.style.display='inline'; Codehighlighter1_1199_1205_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1199_1205_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1199_1205_Closed_Text.style.display='none'; Codehighlighter1_1199_1205_Open_Image.style.display='inline'; Codehighlighter1_1199_1205_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　　　　　　　　　</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:</span><span id="Codehighlighter1_1199_1205_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_1199_1205_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">父进程</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　　close(clifd);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　　</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　　　　　　　}</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　　　　　　}</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />　　　　　　}</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span></div>　　4.<b>程序说明</b><br /><br />　　该程序的功能是监听8888端口的连接,对所有的对8888端口的连接显示出地址和对方的端口号该程序在sco unix下调试通过，在其他unix和linux平台请注意inet_ntoa,htons函数所应在的头文件的名称<br /><br />　　同时该程序用到了并发的观点，因为accept,read,write均为阻塞(block)的函数，一旦进程block将不能处理其他请求，所以用主进程进行listen,由子进程进行负责对客户端传输数据. <br /><br />　　你可以在同一台unix机器用telnet localhost 8888进行观察程序会输出connect from 127.0.0.1 xxxx<br /></sys></sys><img src ="http://www.cppblog.com/tx7do/aggbug/5951.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:17 <a href="http://www.cppblog.com/tx7do/articles/5951.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP/IP编程实现远程文件传输</title><link>http://www.cppblog.com/tx7do/articles/5950.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:16:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5950.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5950.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5950.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5950.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5950.html</trackback:ping><description><![CDATA[
		<table style="WORD-BREAK: break-all; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td valign="top">
										<br />TCP/IP编程实现远程文件传输 <br />   <br />    在TCP/IP网络结构中，为了保证网络安全，网络人员往往需要在路由器上添加防火墙，禁止非法用户用ftp等安全危害较大的TCP/IP协议访问主机。而有时系统维护人员需要用ftp将一些文件从中心机房主机传到前端网点主机上，比如应用程序的替换升级。如果每次传输文件时都要打开防火墙，未免显得有些繁琐，要是在自己的应用程序中增加一个专门的文件传输模块，那将是十分愉快的事情。 <br />  <br />　　UNIX网络程序设计一般都采用套接字(socket)系统调用。针对目前十分流行的客户/服务器模式，其程序编写步骤如下： <br />　　1.Socket系统调用 <br />　　为了进行网络I/O，服务器和客户机两端的UNIX进程要做的第一件事是调用socket()系统调用，建立软插座，指明合适的通讯协议。格式为： <br />　　＃include&lt;sys/types.h&gt; <br />　　＃include&lt;sys/socket.h&gt; <br />　　int socket(int family,int type,int protocol) <br />　　其中：(1)family指明套节字族，其值包括： <br />　　AF_UNIX　　 (UNIX内部协议族) <br />　　AF_INET　　 (Iternet协议) <br />　　AF_NS (XeroxNs协议，TCP/IP编程取该值) <br />　　AF_IMPLINK　 (IMP链接层) <br />　　(2)type 指明套接字类型，取值有： <br />　　SOCK_STREAM 　　　　(流套接字) <br />　　SOCK_DGRAM 　　　　(数据报套接字) <br />　　SOCK_RAW　 　　　　(原始套接字) <br />　　SOCK_SEQPACKET　　 (定序分组套接字) <br />　　一般情况下，前两个参数的组合就可以决定所使用的协议，这时第三个参数被置为0，如果第一个参数为AF_INET，第二个参数选SOCK_STREAM，则使用的协议为TCP；第二个参数选SOCK_DGRAM，则使用的协议为UDP；当第二个参数选SOCK_RAW时，使用的协议为IP。值得指出的是并不是所有的族和类型的组合都是合法的，具体请查阅相关资料。该系统调用若成功则返回一个类似文件描述符，成为套节字描述字，可以像文件描述符那样用read和write对其进行I/O操作。当一个进程使用完该软插座时，需用close(&lt;描述符&gt;<img src="http://www.chinaunix.net/forum/images/smiles/icon_wink.gif" border="0" />关闭(具体见后面内容)。 <br />　　2.服务器端Bind系统调用 <br />　　软插座创建时并没有与任何地址相关联，必须用bind()系统调用为其建立地址联系。其格式为： <br />　　＃include&lt;sys/types.h&gt; <br />　　＃include&lt;sys/socket.h&gt; <br />　　int bind(int socketfd,struct sockaddr_in ＊localaddr,sizeof(localaddr)); <br />　　其中：(1)第一个参数socketfd是前步socket()系统调用返回的套节字描述符。 <br />　　(2)第二个参数被捆向本地地址的一种结构，该结构在sys/netinet/in.h中定义： <br />　　struct sockaddr_in{ <br />　　　short sin_family;/＊socket()系统调用的协议族如AF_INET＊/ <br />　　　u_short sin_port;/＊网络字节次序形式的端口号码＊/ <br />　　　struct in_addr sin_addr;/＊网络字节次序形式的网络地址＊/ <br />　　　char sin_zero[8]; <br />　　} <br />　　一台机器上的每个网络程序使用一个各自独立的端口号码，例如：telnet程序使用端口号23，而ftp文件传输程序使用端口号21。我们在设计应用程序时，端口号码可以由getservbyname()函数从/etc/services库文件中获取，也可以由htons (int portnum)函数将任意正整数转换为网络字节次序形式来得到，有些版本的UNIX操作系统则规定1024以下的端口号码只可被超级用户使用，普通用户程序使用的端口号码只限于1025到32767之间。网络地址可以由gethostbyname(char＊hostname)函数得到(该函数和getservbyname()一样都以网络字节次序形式返回所有在他们结构中的数据)，参数hostname为/etc/hosts文件中某一网络地址所对应的机器名。该函数返回一个类型为hostent的结构指针，hostent结构在netdb.h中定义： <br />　　struct hostent{ <br />　　 char ＊h_name; <br />　　 char ＊＊h_aliases; <br />　　 int h_addrtype; <br />　　 int h_length;　　/＊地址长度＊/ <br />　　 char ＊＊h_addr_list; <br />　　 ＃define h_addr h_addr_list[0];/＊地址＊/ <br />　　} <br />　　(3)第三个参数为第二个结构参数的长度，如果调用成功，bind返回0，否则将返回－1并设置errno。 <br />　　3.服务器端系统调用listen，使服务器愿意接受连接 <br />　　格式：int listen(int socketfd,int backlong) <br />　　它通常在socket和bind调用后在accept调用前执行。第二个参数指明在等待服务器执行accept调用时系统可以排队多少个连接要求。此参数常指定为5，也是目前允许的最大值。 <br />　　4.服务器调用accept,以等待客户机调用connect进行连接。格式如下： <br />　　int newsocket=(int socketfd,struct sockaddr_in ＊peer,int＊addrlen); <br />　　该调用取得队列上的第一个连接请求并建立一个具有与sockfd相同特性的套节字。如果没有等待的连接请求，此调用阻塞调用者直到一连接请求到达。连接成功后，该调用将用对端的地址结构和地址长度填充参数peer和addlen，如果对客户端的地址信息不感兴趣，这两个参数用0代替。 <br />　　5.客户端调用connect()与服务器建立连接。格式为： <br />　　connect(int socketfd,struct sockaddr_in ＊servsddr,int addrlen) <br />　　客户端取得套接字描述符后，用该调用建立与服务器的连接，参数socketfd为socket()系统调用返回的套节字描述符，第二和第三个参数是指向目的地址的结构及以字节计量的目的地址的长度(这里目的地址应为服务器地址)。调用成功返回0，否则将返回－1并设置errno。 <br />　　6.通过软插座发送数据 <br />　　一旦建立连接，就可以用系统调用read和write像普通文件那样向网络上发送和接受数据。Read接受三个参数：一个是套节字描述符；一个为数据将被填入的缓冲区，还有一个整数指明要读的字节数，它返回实际读入的字节数，出错时返回－1，遇到文件尾则返回0。Write也接受三个参数：一个是套节字描述符；一个为指向需要发送数据的缓冲区，还有一个整数指明要写入文件的字节个数，它返回实际写入的字节数，出错时返回－1。当然，也可以调用send和recv来对套节字进行读写，其调用与基本的read和write系统调用相似，只是多了一个发送方式参数。 <br />　　7.退出程序时，应按正常方式关闭套节字。格式如下： <br />　　int close(socketfd) <br />　　前面介绍了UNIX客户/服务器模式网络编程的基本思路和步骤。值得指出的是socket编程所涉及的系统调用不属于基本系统调用范围，其函数原形在libsocket.a文件中，因此，在用cc命令对原程序进行编译时需要带－lsocket选项。 <br />　　现在，我们可以针对文章开头提出的问题着手进行编程了。在图示的网络结构中，为使中心机房的服务器能和网点上的客户机进行通信，需在服务器端添加通过路由器1112到客户机的路由，两台客户机也必须添加通过路由器2221到服务器的路由。在服务器的/etc/hosts文件中应该包含下面内容： <br />　　1.1.1.1　　server <br />　　2.2.2.2　　cli1 <br />　　2.2.2.3　　cli2 <br />　　客户机的/etc/hosts文件中应该有本机地址信息和服务器的地址信息，如cli1客户机的/etc/hosts文件： <br />　　2.2.2.2　　cli1 <br />　　1.1.1.1　　server <br />　　网络环境搭建好后，我们可以在服务器端编写fwq.c程序，负责接受客户机的连接请求，并将从源文件中读取的数据发送到客户机。客户机程序khj.c向服务器发送连接请求，接收从服务器端发来的数据，并将接收到的数据写入目标文件。源程序如下： <br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">/</span><span style="COLOR: #000000">＊服务器源程序fwq.c＊</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">types.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">fcntl.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">socket.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">netinet</span><span style="COLOR: #000000">/</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">netdb.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">errno.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />main() <br /><img id="Codehighlighter1_180_2609_Open_Image" onclick="this.style.display='none'; Codehighlighter1_180_2609_Open_Text.style.display='none'; Codehighlighter1_180_2609_Closed_Image.style.display='inline'; Codehighlighter1_180_2609_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_180_2609_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_180_2609_Closed_Text.style.display='none'; Codehighlighter1_180_2609_Open_Image.style.display='inline'; Codehighlighter1_180_2609_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_180_2609_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_180_2609_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> c,buf[</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">],file[</span><span style="COLOR: #000000">30</span><span style="COLOR: #000000">]; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> fromlen,source; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　register </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> k,s,ns; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr_in sin; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> hostent ＊hp; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　system(″clear″); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　printf(″\n″); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　  <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　printf(″\n\n\t\t输入要传输的文件名：″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　scanf(″％s″,file); <br /><img id="Codehighlighter1_448_489_Open_Image" onclick="this.style.display='none'; Codehighlighter1_448_489_Open_Text.style.display='none'; Codehighlighter1_448_489_Closed_Image.style.display='inline'; Codehighlighter1_448_489_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_448_489_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_448_489_Closed_Text.style.display='none'; Codehighlighter1_448_489_Open_Image.style.display='inline'; Codehighlighter1_448_489_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> ((source</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">open(file,O_RDONLY))</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_448_489_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_448_489_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　perror(″源文件打开出错″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　printf(″\n\t\t在传送文件，稍候…″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　hp</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">gethostbyname(″server″); <br /><img id="Codehighlighter1_571_617_Open_Image" onclick="this.style.display='none'; Codehighlighter1_571_617_Open_Text.style.display='none'; Codehighlighter1_571_617_Closed_Image.style.display='inline'; Codehighlighter1_571_617_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_571_617_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_571_617_Closed_Text.style.display='none'; Codehighlighter1_571_617_Open_Image.style.display='inline'; Codehighlighter1_571_617_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (hp</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">NULL)</span><span id="Codehighlighter1_571_617_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_571_617_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　 perror(″返回主机地址信息错</span><span style="COLOR: #000000">!!!</span><span style="COLOR: #000000">″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　 exit(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　s</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">socket(AF_INET,SOCK_STREAM,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">); <br /><img id="Codehighlighter1_665_713_Open_Image" onclick="this.style.display='none'; Codehighlighter1_665_713_Open_Text.style.display='none'; Codehighlighter1_665_713_Closed_Image.style.display='inline'; Codehighlighter1_665_713_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_665_713_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_665_713_Closed_Text.style.display='none'; Codehighlighter1_665_713_Open_Image.style.display='inline'; Codehighlighter1_665_713_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(s</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_665_713_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_665_713_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　 perror(″获取SOCKET号失败</span><span style="COLOR: #000000">!!!</span><span style="COLOR: #000000">″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　 exit(</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　sin.sin_family</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">AF_INET; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　sin.sin_port</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">htons(</span><span style="COLOR: #000000">1500</span><span style="COLOR: #000000">);</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">＊使用端口1500＊</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　bcopy(hp－</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">h_addr,＆sin.sin_addr,hp－</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">h_length); <br /><img id="Codehighlighter1_865_935_Open_Image" onclick="this.style.display='none'; Codehighlighter1_865_935_Open_Text.style.display='none'; Codehighlighter1_865_935_Closed_Image.style.display='inline'; Codehighlighter1_865_935_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_865_935_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_865_935_Closed_Text.style.display='none'; Codehighlighter1_865_935_Open_Image.style.display='inline'; Codehighlighter1_865_935_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(bind(s,＆sin,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(sin))</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_865_935_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_865_935_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　perror(″不能将服务器地址捆绑到SOCKET号上</span><span style="COLOR: #000000">!!!</span><span style="COLOR: #000000">″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　colse(s); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　exit(</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　}</span></span><span style="COLOR: #000000"> <br /><img id="Codehighlighter1_956_1002_Open_Image" onclick="this.style.display='none'; Codehighlighter1_956_1002_Open_Text.style.display='none'; Codehighlighter1_956_1002_Closed_Image.style.display='inline'; Codehighlighter1_956_1002_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_956_1002_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_956_1002_Closed_Text.style.display='none'; Codehighlighter1_956_1002_Open_Image.style.display='inline'; Codehighlighter1_956_1002_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(listen(s，</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span id="Codehighlighter1_956_1002_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_956_1002_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　perror(″sever:listen″); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　exit(</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　}</span></span><span style="COLOR: #000000"> <br /><img id="Codehighlighter1_1013_1313_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1013_1313_Open_Text.style.display='none'; Codehighlighter1_1013_1313_Closed_Image.style.display='inline'; Codehighlighter1_1013_1313_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1013_1313_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1013_1313_Closed_Text.style.display='none'; Codehighlighter1_1013_1313_Open_Image.style.display='inline'; Codehighlighter1_1013_1313_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_1013_1313_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1013_1313_Open_Text"><span style="COLOR: #000000">{ <br /><img id="Codehighlighter1_1052_1098_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1052_1098_Open_Text.style.display='none'; Codehighlighter1_1052_1098_Closed_Image.style.display='inline'; Codehighlighter1_1052_1098_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1052_1098_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1052_1098_Closed_Text.style.display='none'; Codehighlighter1_1052_1098_Open_Image.style.display='inline'; Codehighlighter1_1052_1098_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((ns</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">accept(s,＆sin,＆fromlen))</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_1052_1098_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1052_1098_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　perror(″sever:accept″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　exit(</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　lseek(source,OL,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">＊每次接受客户机连接，应将用于读的源文件指针移到文件头＊</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　write(ns,file,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(file))； </span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">＊发送文件名＊</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">((k</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">read(source,buf,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(buf)))</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">) <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　 write(ns,buf,k); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　printf(″\n\n\t\t传输完毕</span><span style="COLOR: #000000">!!!</span><span style="COLOR: #000000">\n″); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　close(ns); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　close(source); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　exit(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">＊客户机源程序khj.c＊</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">types.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">fcntl.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">socket.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">netinet</span><span style="COLOR: #000000">/</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">netdb.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　＃include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">errno.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　＃include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　main() <br /><img id="Codehighlighter1_1569_2607_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1569_2607_Open_Text.style.display='none'; Codehighlighter1_1569_2607_Closed_Image.style.display='inline'; Codehighlighter1_1569_2607_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1569_2607_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1569_2607_Closed_Text.style.display='none'; Codehighlighter1_1569_2607_Open_Image.style.display='inline'; Codehighlighter1_1569_2607_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　</span><span id="Codehighlighter1_1569_2607_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1569_2607_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> buf[</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">],file[</span><span style="COLOR: #000000">30</span><span style="COLOR: #000000">]; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> ＊strs</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">″\n\n\t\t正在接收文件″； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> target; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　register </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> k,s; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> sockaddr_in sin; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000"> hostent ＊hp; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　system(″clear″); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　printf(″\n″); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　  <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　hp</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">gethostbyname(″server″); <br /><img id="Codehighlighter1_1821_1877_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1821_1877_Open_Text.style.display='none'; Codehighlighter1_1821_1877_Closed_Image.style.display='inline'; Codehighlighter1_1821_1877_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1821_1877_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1821_1877_Closed_Text.style.display='none'; Codehighlighter1_1821_1877_Open_Image.style.display='inline'; Codehighlighter1_1821_1877_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(hp</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">NULL)</span><span id="Codehighlighter1_1821_1877_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1821_1877_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　　　　　　　perror(″返回服务器地址信息错</span><span style="COLOR: #000000">!!!</span><span style="COLOR: #000000">″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　 　exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　　}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　s</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">socket(AF_INET，SOCK_STREAM,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">); <br /><img id="Codehighlighter1_1927_1978_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1927_1978_Open_Text.style.display='none'; Codehighlighter1_1927_1978_Closed_Image.style.display='inline'; Codehighlighter1_1927_1978_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1927_1978_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1927_1978_Closed_Text.style.display='none'; Codehighlighter1_1927_1978_Open_Image.style.display='inline'; Codehighlighter1_1927_1978_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(s</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_1927_1978_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1927_1978_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　perror(″获取SOCKET号失败</span><span style="COLOR: #000000">!!!</span><span style="COLOR: #000000">″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　exit(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　　}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　sin.sin_family</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">AF_INET; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　sin.sin_port</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">htons(</span><span style="COLOR: #000000">1500</span><span style="COLOR: #000000">);</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">＊端口号需与服务器程序使用的一致＊</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　bcopy(hp－</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">h_addr,＆sin.sin_addr,hp－</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">h_length); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　printf(″\n\n\t\t正在与服务器连接…″)； <br /><img id="Codehighlighter1_2183_2231_Open_Image" onclick="this.style.display='none'; Codehighlighter1_2183_2231_Open_Text.style.display='none'; Codehighlighter1_2183_2231_Closed_Image.style.display='inline'; Codehighlighter1_2183_2231_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_2183_2231_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2183_2231_Closed_Text.style.display='none'; Codehighlighter1_2183_2231_Open_Image.style.display='inline'; Codehighlighter1_2183_2231_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(connect(s,＆sin,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(sin),</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_2183_2231_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_2183_2231_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　perror(″不能与服务器连接</span><span style="COLOR: #000000">!!!</span><span style="COLOR: #000000">″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　exit(</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　　}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">((k</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">read(s,file,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(file)))</span><span style="COLOR: #000000">&lt;=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">＊接收文件名＊</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> <br /><img id="Codehighlighter1_2344_2390_Open_Image" onclick="this.style.display='none'; Codehighlighter1_2344_2390_Open_Text.style.display='none'; Codehighlighter1_2344_2390_Closed_Image.style.display='inline'; Codehighlighter1_2344_2390_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_2344_2390_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2344_2390_Closed_Text.style.display='none'; Codehighlighter1_2344_2390_Open_Image.style.display='inline'; Codehighlighter1_2344_2390_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　 </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">((target</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">open(file,o_WRONLY</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">O_CREAT</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">O_TRUNC,</span><span style="COLOR: #000000">0644</span><span style="COLOR: #000000">))</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_2344_2390_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_2344_2390_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　perror(″不能打开目标文件</span><span style="COLOR: #000000">!!</span><span style="COLOR: #000000">″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　　exit(</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　strcat(strs,file); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　strcat(strs,″，稍候…″)； <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　write(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,strs,strlen(strs)); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">((k</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">read(s,buf,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(buf)))</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">) <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　　write(tatget,buf,k); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　printf(″\n\n\t\t接收文件成功</span><span style="COLOR: #000000">!!!</span><span style="COLOR: #000000">\n″); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　close(s); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />　　close(target); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　}</span></span><span style="COLOR: #000000"> </span></span></div><br />　　上述程序在Sco Unix System v3.2及Sco TCP/IP Rumtime环境下调试通过。<br /></td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cppblog.com/tx7do/aggbug/5950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:16 <a href="http://www.cppblog.com/tx7do/articles/5950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AF_UNIX 地址系列</title><link>http://www.cppblog.com/tx7do/articles/5949.html</link><dc:creator>杨粼波</dc:creator><author>杨粼波</author><pubDate>Thu, 20 Apr 2006 09:15:00 GMT</pubDate><guid>http://www.cppblog.com/tx7do/articles/5949.html</guid><wfw:comment>http://www.cppblog.com/tx7do/comments/5949.html</wfw:comment><comments>http://www.cppblog.com/tx7do/articles/5949.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tx7do/comments/commentRss/5949.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tx7do/services/trackbacks/5949.html</trackback:ping><description><![CDATA[
		<p>AF_UNIX 地址系列（使用 AF_UNIX 或 AF_UNIX_CCSID 地址系列的套接字）可以是面向连接的（类型 SOCK_STREAM），也可以是无连接的（类型 SOCK_DGRAM）。两种类型都很可靠，原因是没有连接两个进程的外部通信函数。 
</p>
		<p>UNIX 域数据报套接字的运行方式与 UDP 数据报套接字有所不同。借助 UDP 数据报套接字，客户机程序就不必调用 <b>bind()</b> 函数，原因是系统会自动指定未使用的端口号。于是服务器可将数据报发送回该端口号。但是，使用 UNIX 域数据报套接字，系统不会自动指定客户机的路径名。因此，使用 UNIX 域数据报的所有客户机程序必须调用 <b>bind()</b> 函数。在客户机的 <b>bind()</b> 上指定的精确路径名就是传递至服务器的路径名。因此，如果客户机指定相对路径名（即，并非以 / 开头的全限定路径名），除非服务器以同一当前目录运行，否则它不能向客户机发送数据报。 
</p>
		<p>应用程序可能对此地址系列使用的示例路径名就是 /tmp/myserver 或 servers/thatserver。借助 servers/thatserver，可使用并非全限定（未指定 /）的路径名。这表示该项在文件系统层次结构中的位置应根据当前工作目录确定。 
</p>
		<dl>
				<dt>
						<b>注意:</b>
				</dt>
				<dd>文件系统中的路径名是启用了 NLS 的。 </dd>
		</dl>
		<p>下图举例说明了 AF_UNIX 地址系列的客户机／服务器关系。有关将环境设置为使用 AF_UNIX 地址系列的详细信息，参见<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/rzab6/rzab6prerequisites.htm#HDRPREREQUISITES">套接字编程的先决条件</a>。 
</p>
		<p>
				<br />
				<img alt="在服务器和客户机 AF_UNIX 地址系列示例程序中使用的套接字事件流。" src="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/rzab6/rzab6503.gif" />
				<br />
		</p>
		<p>
				<b>套接字事件流：使用 AF_UNIX 地址系列的服务器应用程序</b>
				<br />
				<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/rzab6/rzab6xafunixsrv.htm#HDRXAFUNIXSRV">示例：使用 AF_UNIX 地址系列的服务器应用程序</a>使用以下函数调用序列： 
</p>
		<ol type="1">
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/socket.htm">socket()</a>
						</b> 函数返回表示端点的套接字描述符。该语句还标识将对此套接字使用带有流传输（SOCK_STREAM）的 UNIX 地址系列。该函数返回表示端点的套接字描述符。还可使用 <b><a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/socketp.htm">socketpair()</a></b> 函数初始化 UNIX 套接字。 
<p>AF_UNIX 或 AF_UNIX_CCSID 是支持 <b>socketpair()</b> 函数的唯一地址系列。<b>socketpair()</b> 函数返回未命名的和已连接的套接字描述符。 </p></li>
				<li>在创建套接字描述符之后，<b><a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/bind.htm">bind()</a></b> 函数获取套接字的唯一名称。 
<p>UNIX 域套接字的名称空间由路径名组成。当套接字程序调用 <b>bind()</b> 函数时，会在文件系统目录中创建一项。如果路径名已存在，则 <b>bind()</b> 失败。因此，UNIX 域套接字程序应总是调用 <b><a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/unlink.htm">unlink()</a></b> 函数以在结束时除去该目录项。 </p></li>
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/listen.htm">listen()</a>
						</b> 允许服务器接受入局客户机连接。在此示例中，储备设置为 10。这表示系统将对 10 个入局连接请求排队，然后才开始拒绝入局请求。 
</li>
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/recv.htm">recv()</a>
						</b> 函数从客户机应用程序接收数据。在此示例中，我们知道客户机将发送超过 250 字节的数据。既然如此，就可以使用 SO_RCVLOWAT 套接字选项指定在所有 250 字节数据都到达之前不要唤醒 <b>recv()</b>。 
</li>
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/send.htm">send()</a>
						</b>函数将数据回传至客户机。 
</li>
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/close.htm">close()</a>
						</b> 函数关闭所有打开的套接字描述符。 
</li>
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/unlink.htm">unlink()</a>
						</b> 函数从文件系统除去 UNIX 路径名。 </li>
		</ol>
		<p>
				<b>套接字事件流：使用 AF_UNIX 地址系列的客户机应用程序</b>
				<br />
				<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/rzab6/rzab6xafunixcl.htm#HDRXAFUNIXCL">示例：使用 AF_UNIX 地址系列的客户机应用程序</a>使用以下函数调用序列： 
</p>
		<ol type="1">
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/socket.htm">socket()</a>
						</b> 函数返回表示端点的套接字描述符。该语句还标识将对此套接字使用带有流传输（SOCK_STREAM）的 UNIX 地址系列。该函数返回表示端点的套接字描述符。还可使用 <b><a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/socketp.htm">socketpair()</a></b> 函数初始化 UNIX 套接字。 
<p>AF_UNIX 或 AF_UNIX_CCSID 是支持 <b>socketpair()</b> 函数的唯一地址系列。<b>socketpair()</b> 函数返回未命名的和已连接的套接字描述符。 </p></li>
				<li>接收到套接字描述符后，使用 <b><a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/connec.htm">connect()</a></b> 函数来建立与服务器的连接。 
</li>
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/send.htm">send()</a>
						</b>函数发送指定的 250 字节数据，该数据是在服务器应用程序中使用 SO_RCVLOWAT 套接字选项指定的。 
</li>
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/recv.htm">recv()</a>
						</b> 函数一直循环，直到所有 250 字节数据都到达为止。 
</li>
				<li>
						<b>
								<a href="http://publib.boulder.ibm.com/iseries/v5r2/ic2989/info/apis/close.htm">close()</a>
						</b> 函数关闭所有打开的套接字描述符。 </li>
		</ol>
<img src ="http://www.cppblog.com/tx7do/aggbug/5949.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tx7do/" target="_blank">杨粼波</a> 2006-04-20 17:15 <a href="http://www.cppblog.com/tx7do/articles/5949.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>