??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品综合久久,青青草原综合久久大伊人精品,亚洲国产精品成人久久http://www.shnenglu.com/tx7do/category/1513.html严以律己,宽以待h. 三思而后?</br> GMail/GTalk: yanglinbo#google.com;</br> MSN/Email: tx7do#yahoo.com.cn;</br> QQ: 3 0 3 3 9 6 9 2 0 .zh-cnThu, 10 Jun 2010 17:03:12 GMTThu, 10 Jun 2010 17:03:12 GMT60 Linux Socket~程实例(一个Hello WorldE序) http://www.shnenglu.com/tx7do/articles/5966.html杨粼?/dc:creator>杨粼?/author>Thu, 20 Apr 2006 09:49:00 GMThttp://www.shnenglu.com/tx7do/articles/5966.htmlhttp://www.shnenglu.com/tx7do/comments/5966.htmlhttp://www.shnenglu.com/tx7do/articles/5966.html#Feedback0http://www.shnenglu.com/tx7do/comments/commentRss/5966.htmlhttp://www.shnenglu.com/tx7do/services/trackbacks/5966.html阅读全文

]]>
Linux 下Socket~程基础 http://www.shnenglu.com/tx7do/articles/5962.html杨粼?/dc:creator>杨粼?/author>Thu, 20 Apr 2006 09:40:00 GMThttp://www.shnenglu.com/tx7do/articles/5962.htmlhttp://www.shnenglu.com/tx7do/comments/5962.htmlhttp://www.shnenglu.com/tx7do/articles/5962.html#Feedback0http://www.shnenglu.com/tx7do/comments/commentRss/5962.htmlhttp://www.shnenglu.com/tx7do/services/trackbacks/5962.html 作者: 东北大学U皇岛分校Y件中心技术研发部 敬茂?/td>
1?nbsp;引言
Linux的兴起可以说是Internet创造的一个奇qVLinux作ؓ一个完全开攑օ原代码的免费的自pYӞ兼容了各UUNIX标准Q如POSIX、UNIX System V ?nbsp;BSD UNIX {)的多用户、多d的具有复杂内核的操作pȝ。在中国Q随着Internet的普及,一批主要以高等院校的学生和ISP的技术h员组成的Linux爱好者队伍已l蓬勃成长v来。越来越多的~程爱好者也逐渐L上这个优U的自pY件。本文介l了Linux下Socket的基本概念和函数调用?br>
2?nbsp;什么是Socket
SocketQ套接字Q是通过标准的UNIX文g描述W和其它E序通讯的一个方法。每一个套接字都用一个半相关描述Q{协议Q本地地址、本地端口}来表C;一个完整的套接字则用一个相xqͼ{协议Q本地地址、本地端口、远E地址、远E端口}Q每一个套接字都有一个本地的由操作系l分配的唯一的套接字受?br>
3?nbsp;Socket的三U类?br>Q?Q?nbsp;式SocketQSOCK_STREAMQ?br>式套接字提供可靠的、面向连接的通信;它用TCP协议Q从而保证了数据传输的正性和序的?br>Q?Q?nbsp;数据报SocketQSOCK_DGRAMQ?br>数据报套接字定义了一U无q接的服务,数据通过怺独立的报文进行传输,是无序的Qƈ且不保证可靠、无差错。它使用数据报协议UDP
Q?Q?nbsp;原始Socket
原始套接字允许对底层协议如IP或ICMP直接讉KQ它功能强大但用较Z便,主要用于一些协议的开发?br>
4?nbsp;利用套接字发送数?br>1?nbsp;对于式套接字用pȝ调用sendQ)来发送数据?br>2?nbsp;对于数据报套接字Q则需要自己先加一个信息头Q然后调用sendtoQ)函数把数据发送出厅R?br>
5?nbsp;Linux中Socket的数据结?br>Q?Q?nbsp;struct sockaddr { //用于存储套接字地址
unsigned short sa_familyQ?/地址cd
char sa_data[14]Q?nbsp;//14字节的协议地址
}Q?br>Q?Q?nbsp;struct sockaddr_in{ //in 代表internet
short int sin_familyQ?nbsp;//internet协议?br>unsigned short int sin_portQ?/端口P必须是网l字节顺?br>struct in_addr sin_addrQ?/internet地址Q必L|络字节序
unsigned char sin_zeroQ?/?Q和struct sockaddr一样大?br>}Q?br>Q?Q?nbsp;struct in_addr{
unsigned long s_addrQ?br>}Q?br>
6?nbsp;|络字节序及其转换函数
Q?Q?nbsp;|络字节序
每一台机器内部对变量的字节存储顺序不同,而网l传输的数据是一定要l一序的。所以对内部字节表示序与网l字节顺序不同的机器Q一定要Ҏ据进行{换,从程序的可移植性要求来Ԍq本机的内部字节表C顺序与|络字节序相同也应该在传输数据以前先调用数据{换函敎ͼ以便E序UL到其它机器上后能正确执行。真正{换还是不转换是由pȝ函数自己来决定的?br>Q?Q?nbsp;有关的{换函?br>* unsigned short int htonsQunsigned short int hostshortQ:
L字节序转换成网l字节顺序,ҎW号短型q行操作4bytes
* unsigned long int htonlQunsigned long int hostlongQ:
L字节序转换成网l字节顺序,ҎW号长型q行操作8bytes
* unsigned short int ntohsQunsigned short int netshortQ:
|络字节序转换成主机字节顺序,ҎW号短型q行操作4bytes
* unsigned long int ntohlQunsigned long int netlongQ:
|络字节序转换成主机字节顺序,ҎW号长型q行操作8bytes
注:以上函数原型定义在netinet/in.h?br>
7?nbsp;IP地址转换
有三个函数将数字点Ş式表C的字符串IP地址?2位网l字节顺序的二进制Ş式的IP地址q行转换
Q?Q?nbsp;unsigned long int inet_addr(const char * cp)Q该函数把一个用数字和点表示的IP地址的字W串转换成一个无W号长整型,如:struct sockaddr_in ina
ina.sin_addr.s_addr=inet_addr("202.206.17.101")
该函数成功时Q返回{换结果;p|时返回常量INADDR_NONEQ该帔R=-1Q二q制的无W号整数-1相当?55.255.255.255Q这是一个广播地址Q所以在E序中调用iner_addrQ)Ӟ一定要Zؓ地对调用p|q行处理。由于该函数不能处理q播地址Q所以在E序中应该用函数inet_atonQ)?br>Q?Qint inet_atonQconst char * cp,struct in_addr * inpQ:此函数将字符串Ş式的IP地址转换成二q制形式的IP地址Q成功时q回1Q否则返?Q{换后的IP地址存储在参数inp中?br>Q?Q?nbsp;char * inet_ntoaQstruct in-addr inQ:?2位二q制形式的IP地址转换为数字点形式的IP地址Q结果在函数q回gq回Q返回的是一个指向字W串的指针?br>
8?nbsp;字节处理函数
Socket地址是多字节数据Q不是以I字W结Q这和C语言中的字符串是不同的。Linux提供了两l函数来处理多字节数据,一l以bQbyteQ开_是和BSDpȝ兼容的函敎ͼ另一l以memQ内存)开_是ANSI C提供的函数?br>以b开头的函数有:
Q?Q?nbsp;void bzeroQvoid * s,int nQ:参数s指定的内存的前n个字节设|ؓ0Q通常它用来将套接字地址??br>Q?Q?nbsp;void bcopyQconst void * srcQvoid * destQint nQ:从参数src指定的内存区域拷贝指定数目的字节内容到参数dest指定的内存区域?br>Q?Q?nbsp;int bcmpQconst void * s1Qconst void * s2Qint nQ:比较参数s1指定的内存区域和参数s2指定的内存区域的前n个字节内容,如果相同则返?Q否则返回非0?br>注:以上函数的原型定义在strings.h中?br>以mem开头的函数有:
Q?Q?nbsp;void * memsetQvoid * sQint cQsize_t nQ:参数s指定的内存区域的前n个字节设|ؓ参数c的内宏V?br>Q?Q?nbsp;void * memcpyQvoid * destQconst void * srcQsize_t nQ:功能同bcopyQ)Q区别:函数bcopyQ)能处理参数src和参数dest所指定的区域有重叠的情况,memcpyQ)则不能?br>Q?Q?nbsp;int memcmpQconst void * s1Qconst void * s2Qsize_t nQ:比较参数s1和参数s2指定区域的前n个字节内容,如果相同则返?Q否则返回非0?br>注:以上函数的原型定义在string.h中?br>
9?nbsp;基本套接字函?br>Q?Q?nbsp;socketQ)
#include< sys/types.h> 
#include< sys/socket.h> 
int socket(int domainQint typeQint protocol)
参数domain指定要创建的套接字的协议族,可以是如下|
AF_UNIX //UNIX域协议族Q本机的q程间通讯时?br>AF_INET //Internet协议族(TCP/IPQ?br>AF_ISO //ISO协议?br>参数type指定套接字类型,可以是如下|
SOCK_STREAM //套接字Q面向连接的和可靠的通信cd
SOCK_DGRAM //数据报套接字Q非面向q接的和不可靠的通信cd
SOCK_RAW //原始套接字,只对Internet协议有效Q可以用来直接访问IP协议
参数protocol通常讄?Q表CZ用默认协议,如Internet协议族的套接字使用TCP协议Q而数据报套接字用UDP协议。当套接字是原始套接字类型时Q需要指定参数protocolQ因为原始套接字对多U协议有效,如ICMP和IGMP{?br>Linuxpȝ中创Z个套接字的操作主要是Q在内核中创Z个套接字数据l构Q然后返回一个套接字描述W标识这个套接字数据l构。这个套接字数据l构包含q接的各U信息,如对方地址、TCP状态以及发送和接收~冲区等{,TCP协议Ҏq个套接字数据结构的内容来控制这条连接?br>Q?Q?nbsp;函数connectQ)
#include< sys/types.h> 
#include< sys/socket.h> 
int connectQint sockfdQstruct sockaddr * servaddrQint addrlenQ?br>参数sockfd是函数socketq回的套接字描述W;参数servaddr指定q程服务器的套接字地址Q包括服务器的IP地址和端口号Q参数addrlen指定q个套接字地址的长度。成功时q回0Q否则返?1Qƈ讄全局变量Z下Q何一U错误类型:ETIMEOUT、ECONNREFUSED、EHOSTUNREACH或ENETUNREACH?br>在调用函数connect之前Q客h需要指定服务器q程的套接字地址。客h一般不需要指定自q套接字地址QIP地址和端口号Q,pȝ会自动从1024?000的端口号范围内ؓ它选择一个未用的端口P然后以这个端口号和本机的IP地址填充q个套接字地址?br>客户用函数connect来主动徏立连接。这个函数将启动TCP协议?ơ握手过E。在建立q接之后或发生错误时函数q回。连接过E可能出现的错误情况有:
Q?Q?nbsp;如果客户机TCP协议没有接收到对它的SYN数据D늚认Q函C错误q回Q错误类型ؓETIMEOUT。通常TCP协议在发送SYN数据D失败之后,会多ơ发送SYN数据D,在所有的发送都高中p|之后Q函C错误q回?br>注:SYNQsynchronizeQ位Q请求连接。TCP用这U数据段向对方TCP协议h建立q接。在q个数据D中QTCP协议它选择的初始序列号通知ҎQƈ且与Ҏ协议协商最大数据段大小。SYN数据D늚序列号ؓ初始序列Pq个SYN数据D能够被认。当协议接收到对q个数据D늚认之后Q徏立TCPq接?br>Q?Q?nbsp;如果q程TCP协议q回一个RST数据D,函数立即以错误返回,错误cd为ECONNREFUSED。当q程机器在SYN数据D|定的目的端口号处没有服务q程在等待连接时Q远E机器的TCP协议发送一个RST数据D,向客h报告q个错误。客h的TCP协议在接收到RST数据D后不再l箋发送SYN数据D,函数立即以错误返回?br>注:RSTQresetQ位Q表C求重|连接。当TCP协议接收C个不能处理的数据D|Q向ҎTCP协议发送这U数据段Q表C个数据段所标识的连接出C某种错误Q请求TCP协议这个连接清除。有3U情况可能导致TCP协议发送RST数据D:Q?QSYN数据D|定的目的端口处没有接收进E在{待Q(2QTCP协议x弃一个已l存在的q接Q(3QTCP接收C个数据段Q但是这个数据段所标识的连接不存在。接收到RST数据D늚TCP协议立即这条连接非正常地断开Qƈ向应用程序报告错误?br>Q?Q?nbsp;如果客户机的SYN数据D导致某个\由器产生“目的C可到?#8221;cd的ICMP消息Q函C错误q回Q错误类型ؓEHOSTUNREACH或ENETUNREACH。通常TCP协议在接收到q个ICMP消息之后Q记录这个消息,然后l箋几次发送SYN数据D,在所有的发送都告失败之后,TCP协议查这个ICMP消息Q函C错误q回?br>注:ICMPQInternet 消息控制协议。Internet的运行主要是由Internet的\由器来控Ӟ路由器完成IP数据包的发送和接收Q如果发送数据包时发生错误,路由器用ICMP协议来报告这些错误。ICMP数据包是装在IP数据包的数据部分中进行传输的Q其格式如下Q?br>cd
?nbsp;
校验?br>数据
0 8 16 24 31
cdQ指出ICMP数据包的cd?br>代码Q提供ICMP数据包的q一步信息?br>校验和:提供了对整个ICMP数据包内容的校验和?br>ICMP数据包主要有以下cdQ?br>Q?Q?nbsp;目的C可到达:A、目的主机未q行QB、目的地址不存在;C、\p中没有目的地址对应的条目,因而\由器无法扑ֈd目的L的\由?br>Q?Q?nbsp;时Q\由器接收到的IP数据包的生存旉QTTLQ域?Q如果这个域的值变?Q\由器丢弃q个IP数据包,q且发送这UICMP消息?br>Q?Q?nbsp;参数出错Q当IP数据包中有无效域时发送?br>Q?Q?nbsp;重定向:一条新的\径通知L?br>Q?Q?nbsp;ECHOh、ECHO回答Q这两条消息用语试目的L是否可以到达。请求者向目的L发送ECHOhICMP数据包,目的L在接收到q个ICMP数据包之后,q回ECHO回答ICMP数据包?br>Q?Q?nbsp;时戳h、时戛_{:ICMP协议使用q两U消息从其他机器处获得其旉的当前时间?br>
调用函数connect的过E中Q当客户机TCP协议发送了SYN数据D늚认之后QTCP状态由CLOSED状态{为SYN_SENT状态,在接收到对SYN数据D늚认之后QTCP状态{换成ESTABLISHED状态,函数成功q回。如果调用函数connectp|Q应该用close关闭q个套接字描q符Q不能再ơ用这个套接字描述W来调用函数connect?br>
注:TCP协议状态{换图Q?br>
被动OPEN CLOSE dOPEN
Q徏立TCBQ?nbsp;Q删除TCBQ?nbsp;Q徏立TCBQ?br>发送SYNQ?br>接收SYN SEND
Q发送SYNQACKQ?nbsp;Q发送SYNQ?br>
接收SYN的ACKQ无动作Q?nbsp;
接收SYN的ACK 接收SYNQACK 
Q无动作Q?nbsp;Q发送ACKQ?br>CLOSE
Q发送FINQ?nbsp;CLOSE 接收FIN
Q发送FINQ?nbsp;Q发送FINQ?br>
接收FIN
接收FIN的ACKQ无动作Q?nbsp;Q发送ACKQ?nbsp;CLOSEQ发送FINQ?br>

接收FIN 接收FIN的ACK 接收FIN的ACK
Q发送ACKQ?nbsp;Q无动作Q?nbsp;Q无动作Q?br>
2MSL时Q删除TCBQ?nbsp;
Q?Q?nbsp;函数bindQ)
函数bind本地地址与套接字l定在一P其定义如下:
#include< sys/types.h> 
#include< sys/socket.h> 
int bind(int sockfd,struct sockaddr * myaddr,int addrlen)Q?br>参数sockfd是函数socktq回的套接字描述W;参数myaddr是本地地址Q参数addrlen是套接字地址l构的长度。执行成功时q回0Q否则,q回-1Qƈ讄全局变量errno为错误类型EADDRINUSER?br>服务器和客户机都可以调用函数bind来绑定套接字地址Q但一般是服务器调用函数bind来绑定自q公认端口受绑定操作一般有如下几种l合方式Q?br>?
E序cd
IP地址
端口?br>说明
服务?br>INADDR_ANY
非零?br>指定服务器的公认端口?br>服务?br>本地IP地址
非零?br>指定服务器的IP地址和公认端口号
客户?br>INADDR_ANY
非零?br>指定客户机的q接端口?br>客户?br>本地IP地址
非零?br>指定客户机的IP地址q接端口?br>客户?br>本地IP地址
?br>指定客户机的IP地址
分别说明如下Q?br>Q?Q?nbsp;服务器指定套接字地址的公认端口号Q不指定IP地址Q即服务器调用bindӞ讄套接字的IP地址为特D的INADDE-ANYQ表C它愿意接收来自M|络讑֤接口的客hq接。这是服务器最常用的绑定方式?br>Q?Q?nbsp;服务器指定套接字地址的公认端口号和IP地址Q服务器调用bindӞ如果讄套接字的IP地址为某个本地IP地址Q这表示q台机器只接收来自对应于q个IP地址的特定网l设备接口的客户接。当服务器有多块|卡Ӟ可以用这U方式来限制服务器的接收范围?br>Q?Q?nbsp;客户机指定套接字地址的连接端口号Q一般情况下Q客h调用connect函数时不用指定自q套接字地址的端口号。系l会自动为它选择一个未用的端口Pq且用本地的IP地址来填充套接字地址中的相应V但有时客户机需要用一个特定的端口P比如保留端口PQ而系l不会未客户动分配一个保留端口号Q所以需要调用函数bind来和一个未用的保留端口L定?br>Q?Q?nbsp;指定客户机的IP地址和连接端口号Q表C客h使用指定的网l设备接口和端口可行通信?br>Q?Q?nbsp;指定客户机的IP地址Q表C客h使用指定的网l设备接口和端口可行通信Q系l自动ؓ客户机选一个未用的端口受一般只有在L有多个网l设备接口时使用?br>我们一般不在客h上用固定的客户机端口号Q除非是必须使用的情c在客户Z使用固定的端口号有以下不利:
Q?Q?nbsp;服务器执行主动关闭操作:服务器最后进入TIME_WAIT状态。当客户机再ơ与q个服务器进行连接时Q仍使用相同的客h端口P于是q个q接与前ơ连接的套接字对完全一P但是一呢、ؓ前次q接处于TIME_WAIT状态,q未消失Q所以这ơ连接请求被拒绝Q函connect以错误返回,错误cd为ECONNREFUSED
Q?Q?nbsp;客户机执行主动关闭操作:客户机最后进入TIME_WAIT状态。当马上再次执行q个客户机程序时Q客hl与q个固定客户机端口号l定Q但因ؓ前次q接处于TIME_WAIT状态,q未消失Q系l会发现q个端口号仍被占用,所以这ơ绑定操作失败,函数bind以错误返回,错误cd为EADDRINUSE?br>Q?Q?nbsp;函数listenQ)
函数listen一个套接字转换为征听套接字Q定义如下;
#include< sys/socket,h> 
int listen(int sockfdQint backlog)
参数sockfd指定要{换的套接字描q符Q参数backlog讄h队列的最大长度;执行成功时返?Q?nbsp;否则q回-1。函数listen功能有两个:
Q?Q?nbsp;一个尚未连接的d套接字(函数socket创徏的可以用来进行主动连接但不能接受q接h的套接字Q{换成一个被动连接套接字。执行listen之后Q服务器的TCP状态由CLOSED转ؓLISTEN状态?br>Q?Q?nbsp;TCP协议到辄q接h队列Q函数listen的第二个参数指定q个队列的最大长度?br>注:参数backlog的作用:
TCP协议为每一个征听套接字l护两个队列Q?br>Q?Q?nbsp;未完成连接队列:每个未完成3ơ握手操作的TCPq接在这个队列中占有一VTCP希望仪在接收C个客hSYN数据D之后,在这个队列中创徏一个新条目Q然后发送对客户机SYN数据D늚认和自qSYN数据D(ACK+SYN数据D)Q等待客h对自qSYN数据D늚认。此Ӟ套接字处于SYN_RCVD状态。这个条目将保存在这个队列中Q直到客hq回对SYN数据D늚认或者连接超时?br>Q?Q?nbsp;完成q接队列Q每个已l完?ơ握手操作,但尚未被应用E序接收Q调用函数acceptQ的TCPq接在这个队列中占有一V当一个在未完成连接队列中的连接接收到对SYN数据D늚认之后Q完?ơ握手操作,TCP协议它从未完成q接队列Ud完成q接队列中。此Ӟ套接字处于ESTABLISHED状态。这个条目将保存在这个队列中Q直到应用程序调用函数accept来接收它?br>参数backlog指定某个征听套接字的完成q接队列的最大长度,表示q个套接字能够接收的最大数目的未接收连接。如果当一个客h的SYN数据D到达时Q征听套接字的完成队列已l满了,那么TCP协议忽略这个SYN数据Dc对于不能接收的SYN数据D,TCP协议不发送RST数据D,
Q?Q?nbsp;函数acceptQ)
函数accept从征听套接字的完成队列中接收一个已l徏立v来的TCPq接。如果完成连接队列ؓI,那么q个q程睡眠?br>#include< sys/socket.h> 
int accept(int sockfdQstruct sockaddr * addrQint * addrlen)
参数sockfd指定征听套接字描q符Q参数addr为指向一个Internet套接字地址l构的指针;参数addrlen为指向一个整型变量的指针。执行成功时Q返?个结果:函数q回gؓ一个新的套接字描述W,标识q个接收的连接;参数addr指向的结构变量中存储客户机地址Q参数addrlen指向的整型变量中存储客户机地址的长度。失败时q回-1?br>征听套接字专为接收客hq接hQ完?ơ握手操作而用的,所以TCP协议不能使用征听套接字描q符来标识这个连接,于是TCP协议创徏一个新的套接字来标识这个要接收的连接,q将它的描述W发挥给应用E序。现在有两个套接字,一个是调用函数accept时用的征听套接字,另一个是函数acceptq回的连接套接字Qconnected socketQ。一个服务器通常只需创徏一个征听套接字Q在服务器进E的整个zd期间Q用它来接收所有客h的连接请求,在服务器q程l止前关闭这个征听套接字Q对于没一个接收的QacceptedQ连接,TCP协议都创Z个新的连接套接字来标识这个连接,服务器用这个连接套接字与客hq行通信操作Q当服务器处理完q个客户求时Q关闭这个连接套接字?br>当函数acceptd{待已经建立的连接时Q如果进E捕获到信号Q函数将以错误返回,错误cd为EINTR。对于这U错误,一般重新调用函数accept来接收连接?br>Q?Q?nbsp;函数closeQ)
函数close关闭一个套接字描述W。定义如下:
#include< unistd.h> 
int close(int sockfd)Q?br>执行成功时返?Q否则返?1。与操作文g描述W的close一P函数close套接字描述W的引用计数器减1Q如果描q符的引用计数大?Q则表示q有q程引用q个描述W,函数close正常q回Q如果ؓ0Q则启动清除套接字描q符的操作,函数close立即正常q回?br>调用close之后Q进E将不再能够讉Kq个套接字,但TCP协议l用这个套接字Q将未发送的数据传递到ҎQ然后发送FIN数据D,执行关闭操作Q一直等到这个TCPq接完全关闭之后QTCP协议才删除该套接字?br>Q?Q?nbsp;函数readQ)和writeQ)
用于从套接字d数据。定义如下:
int read(int fdQchar * bufQint len)
int write(int fdQchar * bufQint len)
函数执行成功Ӟq回L写的数据量的大小Q失败时q回-1?br>每个TCP套接字都有两个缓冲区Q套接字发送缓冲区、套接字接收~冲区,分别处理发送和接收d。从|络诅R写数据的操作是由TCP协议在内怸完成的:TCP协议从|络上接收到的数据保存在相应套接字的接收~冲ZQ等待用戯用函数将它们从接收缓冲区拯到用L冲区Q用户将要发送的数据拯到相应套接字的发送缓冲区中,然后由TCP协议按照一定的法处理q些数据?br>dq接套接字的操作与读写文件的操作cMQ也可以使用函数read和write。函数read完成数据从套接字接收缓冲区拯到用L冲区Q当套接字接收缓冲区有数据可LQ?Q可L据量大于函数read指定|q回函数参数len指定的数据量Q?Q了度数据量于函数read指定|函数read不等待请求的所有数据都到达Q而是立即q回实际d的数据量Q当无数据可LQ函数read阻塞不q回Q等待数据到达?br>当TCP协议接收到FIN数据D,相当于给L作一个文件结束符Q此时read函数q回0Qƈ且以后所有在q个套接字上的读操作均返?Q这和普通文件中遇到文gl束W是一L?br>当TCP协议接收到RST数据D,表示q接出现了某U错误,函数read以错误q回Q错误类型ؓECONNERESET。ƈ且以后所有在q个套接字上的读操作均返回错误。错误返回时q回值小??br>函数write完成数据从用户~冲区拷贝到套接字发送缓冲区的Q务:到套接字发送缓冲区有够拷贝所有用h据的I间Ӟ函数write数据拷贝到q个~冲ZQƈq回老辈的数量大,如果可用I间于write参数len指定的大时Q函数write阻塞不q回Q等待缓冲区有够的I间?br>当TCP协议接收到RST数据D(当对方已l关闭了q条q接之后Ql向q个套接字发送数据将DҎTCP协议q回RST数据D)QTCP协议接收到RST数据D|Q函数write以错误q回Q错误类型ؓEINTR。以后可以l在q个套接字上写数据?br>Q?Q?nbsp;函数getsocknameQ)和getpeernameQ)
函数getsocknameq回套接字的本地地址Q函数getpeernameq回套接字对应的q程地址?br>
10?nbsp;l束?br>|络E序设计全靠套接字接收和发送信息。上文主要讲qCLinux 下Socket的基本概cSockets API以及Socket所涉及到的TCP常识

]]>
socket~程—技术实?/title><link>http://www.shnenglu.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.shnenglu.com/tx7do/articles/5961.html</guid><wfw:comment>http://www.shnenglu.com/tx7do/comments/5961.html</wfw:comment><comments>http://www.shnenglu.com/tx7do/articles/5961.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/tx7do/comments/commentRss/5961.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/tx7do/services/trackbacks/5961.html</trackback:ping><description><![CDATA[ <span id="eimow2u" class="tpc_content"> <font size="2">q几天都在玩socket了,有一点心得,贴出来与大家pQ若有不妥或错误的地方,q请各位看官指点一二?br /><br />什么是socketQsocket是...Q我在这里就不抄书了Q有兴趣的同仁去查查书吧?br />不过q要说一句,socket是不同q程之间的一U通信方式。就象打电话是朋友之间的一U通信方式是一栗个人理解:所谓“通信”,是怺之间发送数据。有人理解socket是不同计机之间的一U通信?br />式,q是不确切的。两个进E,不管是运行在同一台计机上,q是q行在不同计机上,都可通过<br />socket技术进行通信?br /><br />socket套接字的使用需要有|卡的支持,所以socket一般都被用来在不同机器之间通信Q而如果在同一台计机上的两个q程q行通信Q通常采用效率更高的共享内存技术来实现?br /><br />两个q程之间q行通讯Q就需要两个进E同旉在运行了Q废话)Q在具体实现中,两个q程我们通常要区别对待,一个进E专门等待另一个进E给自己发消息,收到消息后进行处理,在把处理l果发送回厅R我们把专门处理消息、提供服务的q程UCؓ服务器端Q把发送消息、请求处理的q程UCؓ客户端。Mq程是客户端发送一个消息给服务器端Q服务器端进E收到消息进行处理,把处理结果发送给客户端。恩Q就是这栗?br /><br />q有一个问题,如果我现在有一个进E要跟另一台计机上的某个q程q行socket通信Q那在我q个q程中如何指定另一个进E呢Q这里还需要说一下另一个概念——端口,如果把操作系l比作一座房子的话,那端口就是房子的H口Q是pȝ外界同系l内部进行通信的通道。在socket实现中,我们不进行另一个进E的指定Q而是指定发送消息或接收消息的端口号。比如说现在q程A要给q程B发消息,我们会把消息发送到q程B所q行的计机的端口N上,而进EB此时正在监视端口NQ这栯EBp收到q程A发送来的数据,同样q程B也把消息发送到该端口上Q进EA也能从该端口收到q程B发送来的数据,当然Q这需要客L和服务器端关于端口号q行一个约定,卛_同操作同一个端口。如果客L把消息发送到端口N1上,而服务器端监视的是端口N2Q那通信一定不能成功。端口号最大ؓ65535Q不能比q个再大了,但在我们自己的程序中量不要用小?024的端口号Q小?024的端口好很多都被pȝ使用了,比如23被telnet所使用?br /><br />socket的实现是很简单的Q只要按照一定的步骤Q就可马上徏立一个这L通信通道?br /><br />下面较详l的介绍几个核心的函敎ͼ<br /><br />SOCKET socket(int af, int type, int protocol);<br />无论是客Lq是服务器端Q下面这个函数是一定要用到的,也是最先用到的?br />q个函数是要告诉pȝQ给我准备好一个socket通道Q我要和其它q程通信了。函数的q回值很重要Q我们要C来,它表C系lؓ我们准备好的q个socket通道Q在以后的每个socket相关函数中都会用刎ͼ如果q个值等于SOCKET_ERRORQ表C函数执行失败了。函数的参数我们分别l:PF_INET、SOCK_STREAM和IPPROTO_TCP?br /><br />int bind(SOCKET s, const sockaddr *addr, int namelen);<br />q个函数只有服务器端E序使用Q作用是与某个socket通道l定。可以用q回值判断该函数执行l果怎么P如果{于SOCKET_ERRORQ那是p|了。第一个参数sQ就是socket()函数的返回|在结构addr中,我们要给定一个端口号Qnamelen{于l构sockaddr的大?br /><br />int listen(SOCKET s, int backlog);<br />q个函数只有服务器端E序使用Q作用是监听该端口。返回gbind函数意义一栗?br /><br />int accept(SOCKET s, sockaddr *addr, int *addrlen);<br />q个函数只有服务器端E序使用Q作用是响应客户端的q接。返回gbind函数意义一栗?br /><br />int connect(SOCKET s, const sockaddr *name, int namelen);<br />q个函数只有客户端程序用,作用是把客户端和某个计算机的某个端口建立q接。返回gbind函数意义一栗第一个参数sQ就是socket()函数的返回|在结构name中,我们要给定一个端口号和目的机器名Qnamelen{于l构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 />q两个函数就是发送数据和接收数据Q客L和服务器端程序都能用Q哪个发送哪个接收不用说了吧Q呵c?br />从函数的q回值可以检查函数执行是否成功。参Cbuf是指向发送或接收的数据的指针Qlen是数据长度。flags我们l个0可以(其实是我不知道具体含义)?br /><br />最后就是关闭socket了,q个很容易忘掉,但这个函数很重要Q一定要用?br />int closesocket(SOCKET s);<br /><br /><br />好了Q关键函数就q么几个Q下图是q几个函数的执行序Q?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() 挂vQ直到有客户端来q接<br />  |     |<br />  v   三段握手q程   |<br />connect() <-------------> |<br />  |     |<br />  v   发送消?  v<br />  +---> send() ---------------> recv() <-------+<br />  |   |     . |<br />  |   |     . 处理消息 |<br />  |   v   响应消息   . |<br />  +---- recv() <--------------- send() --------+<br />  |     |<br />  v     |<br />close() ---------------> recv()<br />    |<br />    v<br />  closesocket()<br /><br />上图我觉得能很好的说明客L和服务器端的q行轨迹?br /><br />使用以上几个函数?linux pȝ上就可成功徏立一个socket通信q\Q但如果在windowspȝ上,q要用到另一个函敎ͼ<br />int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);<br />在windowspȝ上,首先要执行这个函敎ͼ所以要把这个函数放在socket()函数的前面?br /><br />我对上面的函数进行了一些封装,省篇q,我去掉所有注释和非重要的函数Q在q里可以看到各个函数的具体用法:<br /><br />?VC60 环境下要q行下面的函敎ͼ要包含头文g errno.h ?winsock2.hQ还有,在连接的时候要q接上ws2_32.dll文g?br /><br />q是头文件内容:<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 />q是实现文g内容Q?br />bool Socket::setup() {<br /><br />WSADATA wsd;<br />_fd = WSAStartup(MAKEWORD(2,2), &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 *)&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 *)&their_addr,<br />  &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->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 *)&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) && trytimes < CLOSE_TRY_TIMES)<br />trytimes++;<br /><br />if(trytimes == 10) {<br />printf("Cannot close socket!\n");<br />}<br />}<br /><br />好,socketcL装好了Q下面就是组l了Q服务器端和客户端是不一LQ下面分别给Z码,到这里已l就很简单了?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<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 />到q里吧。socket的相兛_容可q不止这些,我在q里只是l大家来个抛砖引玉,xIӞ路还很Oѝ关于详l的实现代码Q去我的《源码》上扑֐Q不攑֜q里Q是Z让篇q小些?/font> </span> <br /> <img src ="http://www.shnenglu.com/tx7do/aggbug/5961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/tx7do/" target="_blank">杨粼?/a> 2006-04-20 17:36 <a href="http://www.shnenglu.com/tx7do/articles/5961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket~程http://www.shnenglu.com/tx7do/articles/5960.html杨粼?/dc:creator>杨粼?/author>Thu, 20 Apr 2006 09:34:00 GMThttp://www.shnenglu.com/tx7do/articles/5960.htmlhttp://www.shnenglu.com/tx7do/comments/5960.htmlhttp://www.shnenglu.com/tx7do/articles/5960.html#Feedback0http://www.shnenglu.com/tx7do/comments/commentRss/5960.htmlhttp://www.shnenglu.com/tx7do/services/trackbacks/5960.html
int SOCK_STREAM
先连接到一C机然后用方式传送数?br />
int SOCK_DGRAM
不连?在数据包中包含目标地址,然后直接送出,包在传送过E中可能丢失和错?br />
int SOCK_RAW
socket数据的底层传?对于一般程序没有什么意?br />

地址的表C方?br />
相关?sys/socket.h
相关数据l构:struct sockaddr *
sockaddr中的两个元素:
===short int sa_family:指出地址的格?br />===char sa_data[14]:地址?br />


地址的格?
AF_LOCAL:本地名称I间(name space)的地址
AF_UNIX:和AF_LOCAL相同,但AF_UNIX是UNIX98标准
AF_FILE:AF_LOCAL的另一个同义词
AF_INET:互联|名U空?对应的名U空间名为PF_INET
AF_INET6:IPv6互联|名U空?br />AF_UNSPEC:用到的地方很?比如清除"带连?的DATAGRAM的目标地址{?对应的名U空间在新版本的libc中已l被d



讄socket地址(在sys/socket.h?

使用bind函数某个地址分配l某个socket
int bind(int socket,struct sock_addr *addr,socklen_t length);
length长度的地址sock_addr分配lsocket
q回0代表成功,q回-1代表p|



dsocket分配到的地址(在sys/socket.h?

使用getsockname函数来得C个socket对应的地址
int getsockname(int socket,struct sockaddr *addr,socklen_t *length-ptr);
socket中的信息攄?addr?length-ptr所指定的空间中
q回?表示成功-1表示p|



|络界面Interface的相兛_量和函数

以下内容在库文gnet/if.h?br />
size_t IFNAMSIZ
表示出容U界面名U的~冲区的大小,包括l束W?

unsigned int nametoindex(const char *ifname);
q回ifname所指出的网l界面的序号,q回0表示此界面不存在

char *if_indextoname(unsigned int ifindex,char *ifname);
扑ֈ一个网l界面序号对应的界面名称,q回值在ifname对应的那D内存空间上,q段I间臛_有IFNAMSIZ?q回ifname表示成功,q回NULL表示p|

struct if_nameindex
q个变量用于存储单个|络界面的信?其中h两个元素:
unsigned int if_index:界面序号
char *if_name:用nulll尾的界面名U?br />
struct if_nameindex *if_nameindex(void);
q回一个struct if_nameindex列表,其中存储了所有界面的信息,最后一个if_nameindex的if_index序号为零,if_name为null
此函数得到的l果必需用if_freenameindex函数清除

void if_freenameindex(struct if_nameindex *ptr);
清除if_nameindex得到的结?br />


本地名称I间(local namespace)

本地名称I间表示为PF_LOCAL(POSIX),PF_UNIX,PF_FILE

本地名称是一个文件名,只能本地调用不能从其他主Zq接

本地socketl构(在sys/socket.h?
struct sockaddr_un
其中包含的元素ؓ
short int sun_family:地址的格式应当设为AF_LOCAL
char sun_path[108]:所要用的文g的文件名(暂时定ؓ108位,可能新的版本中会有所改变)

sun_len函数:
int SUN_LEN(struct sun family *);
具体说应当是SUN_LEN宏,用来l计某个sockaddr_unl构的元素长度和文g名长?不是分配的字节空间的长度)



一个创建本地socket的例?br />#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
int make_named_socket (const char *filename)//此函C用是用filename创徏socket
{
  struct sockaddr_un name;//socket地址名name
  int sock;               //socket
  size_t size;

  /* Create the socket. */
  sock = socket (PF_LOCAL, SOCK_DGRAM, 0);//PF_LOCAL表示本地socket
                                          //SOCK_DGRAM表示数据报方?br />  if (sock < 0)//如创建失败则报错
    {
      perror ("socket";
      exit (EXIT_FAILURE);
    }

  /* Bind a name to the socket. */
  name.sun_family = AF_LOCAL;
  strncpy (name.sun_path, filename, sizeof (name.sun_path));

  /* 地址的长度ؓsockaddr
     l构中filename开始端的偏U量
     加上filename中文件名的长?br />     加上一个字?此字节ؓl束标识)
     或者还可以用宏SUN_LEN:
     size = SUN_LEN (&name);
 */
  size = (offsetof (struct sockaddr_un, sun_path)
          + strlen (name.sun_path) + 1);//开始计?br />
  if (bind (sock, (struct sockaddr *) &name, size) < 0)
    {
      perror ("bind";
      exit (EXIT_FAILURE);
    }

  return sock;
}



关于生成L地址的函?br />
inet_aton(const char *name,struct in_addr *addr);
以字符串表C的地址转换成主机地址q储存在struct in_addr?br />
uint32_t inet_addr(const char *name);
字W串IPv4地址转换成主机地址q返?如失败则q回INADDR_NONE(255.255.255.255);

uint32_t inet_network(const char *name);
停?br />
char *inet_ntoa(struct in_addr addr);
IPv4L地址转换成字W串
注意:此函数的q回的字W串存储在一Dstaticcd的内存空间中,下次调用会覆盖原先的l果,在多U程E序的运行中会出现؜?所以推荐用下文中介绍的inet_ntop

struct in_addr inet_makeaddr(uint32_t net,uint32_t local);
网l号net和主机名locall合成IPv4L地址q返?br />
uint32_t inet_lnaof(struct in_addr addr);
从IPv4|络地址中取Z机名q返?停?

uint32_t inet_netof(struct in_addr addr);
从IPv4|络地址中取出网l号q返?停?

int inet_pton(int af,const char *cp,void *buf);
IPv4或IPv6字符串地址转换成网l主机地址
af:|络地址的格?可取gؓAF_INET和AF_INET6
cp:指向字符串首地址的指?br />buf:指向l果存储I间的指?应当预先分配好够的内存I间存储l果)

const char *inet_ntop(int af,const void *cp,char *buf,size_t len);
IPv4或IPv6|络L地址转换成字W串
af:|络地址的格?可取CؓAF_INET和AF_INET6
cp:指向需要{换的|络地址
buf:指向存储转换l果的内存空?br />len:buf所指向的空间的长度
q回gؓbuf



L名数据库查询的相兛_?br />
struct hostent
其中元素:
char *h_name:L?官方"名称
char **h_aliases:此主机的所有别?br />int h_addrtype:地址cd,可以为AF_INET(IPv4c?和AF_INET6(IPv6c?,也可以出现别的?br />int h_length:地址的大?用字节数计算)
char **h_addr_list:此主机名对应的所有IP,以一个null指针l束
char *h_addr:{于h_addr_list[0]



L名和数据库查询相兛_?br />
struct hostent *gethostbyname(const char *name);
q回L名name的信?如果查询p|则返回一个null指针

struct hostent *gethostbyname2(const char *name,int af);
和gethostbyname盔R?不过可以在af中指出地址格式,可取AF_INET或AF_INET6,分别代表IPv4和IPv6

struct hostent *gethostbyaddr(const char *addr,size_t length,int format);
q回指定|络L的信?addrq指向字符串而是指向一个网l地址,length为addr中地址的长?format为地址的格?可取AF_INET或AF_INET6)



创徏socket

所需函数
int socket(int namespace,int style,int protocol);
namespace:socketcd(比如PF_LOCAL和PF_INET)
style:传输方式(可取SOCK_STREAM和SOCK_DGRAM)
protocol:协议,一般取0



关闭socket

所需函数
int shutdown(int socket,int how);
关闭socket
q回0成功,q回-1p|
how可取gؓ
0:停止接收数据
1:停止送出数据
2:停止接收和读?br />


socket?socket pair)

两个可以互相传送的本地socket,和pipecM,不过pipe为单?socket对ؓ双向

创造socketҎ需函数
int socketpair(int namespace,int style,int protocol,int filedes[2]);
namespace:必需为AF_LOCAL
style:可以取SOCK_STREAM或者SOCK_DGRAM
filedes[2]:创徏的socketҎ在这?img src ="http://www.shnenglu.com/tx7do/aggbug/5960.html" width = "1" height = "1" />

]]>
Socket学习W记之一Q常用基本定义) http://www.shnenglu.com/tx7do/articles/5956.html杨粼?/dc:creator>杨粼?/author>Thu, 20 Apr 2006 09:28:00 GMThttp://www.shnenglu.com/tx7do/articles/5956.htmlhttp://www.shnenglu.com/tx7do/comments/5956.htmlhttp://www.shnenglu.com/tx7do/articles/5956.html#Feedback0http://www.shnenglu.com/tx7do/comments/commentRss/5956.htmlhttp://www.shnenglu.com/tx7do/services/trackbacks/5956.html

常用cd的定义:
Q以下定义从Winsock2.h文g中截取)
/*
 * The new type to be used in all
 * instances which refer to sockets.
 */
typedef UINT_PTR        SOCKET;//SOCKET原来是一个unsigned int的指针而已

/*
 * Select uses arrays of SOCKETs.  These macros manipulate such
 * arrays.  FD_SETSIZE may be defined by the user before including
 * this file, but the default here should be >= 64.
 *
 * CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE
 * INCLUDED IN WINSOCK2.H EXACTLY AS SHOWN HERE.
 */
#ifndef FD_SETSIZE
#define FD_SETSIZE      64
#endif /* FD_SETSIZE */
typedef struct fd_set {
        u_int fd_count;               /* how many are SET? */
        SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
} fd_set;//fd_set是用来select的,表示一个集合,STL中不是有个模板类set?br />//对fd_setl构QWinsock2.h中还定义了四个宏定义来操作fd_set
//FD_CLR(fd, set),FD_SET(fd, set),FD_ZERO(set),FD_ISSET(fd, set)
//一般用法是先定义一个fd_set,使用之前调用fd_zeroQ再一个socket攑ֈfd_set?br />//l过一pd操作后,用fd_isset判断某个socket是否q在set中?br />//SOCKET fd;
//......
//fd_set ReadFds;
//FD_ZERO(&ReadFds);
//FD_SET(fd,&ReadFds);
//.....
//if ( FD_ISSET(fd,&ReadFds) )
//.....
/*
 * Structure used in select() call, taken from the BSD file sys/time.h.
 */
struct timeval {
        long    tv_sec;         /* seconds */
        long    tv_usec;        /* and microseconds */
};//q个也是用于select函数中的Q超时参?br />struct  hostent {//表示L的结?br />        char    FAR * h_name;           /* official name of host */
        char    FAR * FAR * h_aliases;  /* alias list */
        short   h_addrtype;             /* host address type */
        short   h_length;               /* length of address */
        char    FAR * FAR * h_addr_list; /* list of addresses */
#define h_addr  h_addr_list[0]          /* address, for backward compat */
};
/*
 * Internet address (old style... should be updated)//晕,什么时候updateQ?br /> *///原来每次看到in_addrl构都不知道Z么叫in_addr,原来是这栗。?br />struct in_addr {
        union {
                struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { u_short s_w1,s_w2; } S_un_w;
                u_long S_addr; //大部分都用这个变量就够了Q一个ip地址32位刚好一个unsigned longQ?br />        } S_un;
#define s_addr  S_un.S_addr //q样定义以后用的很方便,in_addr.s_addr可以了?br />                                /* can be used for most tcp & ip code */
#define s_host  S_un.S_un_b.s_b2
                                /* host on imp */
#define s_net   S_un.S_un_b.s_b1
                                /* network */
#define s_imp   S_un.S_un_w.s_w2
                                /* imp */
#define s_impno S_un.S_un_b.s_b4
                                /* imp # */
#define s_lh    S_un.S_un_b.s_b3
                                /* logical host */
};
//qb1Qb2Qb3Qb4Qw1Qw2不知道有乜用Q代表乜意思。。?br />#endif
/*
 * Socket address, internet style.
 */
struct sockaddr_in {
        short   sin_family;//地址家族一般都是AF_INET或者PF_INET
        u_short sin_port;//端口
        struct  in_addr sin_addr;//ip地址
        char    sin_zero[8];
};
/*
 * Structure used by kernel to store most//计算机内怸处理用的是这U表C?br /> * addresses.
 */
struct sockaddr {
        u_short sa_family;              /* address family */
        char    sa_data[14];            /* up to 14 bytes of direct address */
};
//仔细一下sockaddr_in和sockaddr两个l构的大是一P所以可以直接强制类型{换赋?br />//比如accept函数其中一个参数类型struct sockaddr FAR * Q你如果有一个struct sockaddr_in myaddr
//可以直接accept(..(struct sockaddr *)myaddr.....
/*
 * WinSock 2 extension -- WSABUF and QOS struct, include qos.h
 * to pull in FLOWSPEC and related definitions
 */
typedef struct _WSABUF {//~冲区,一般ms在带WSA前缀的acceptQreceiveQsend{函C才用?br />    u_long      len;     /* the length of the buffer */
    char FAR *  buf;     /* the pointer to the buffer */
} WSABUF, FAR * LPWSABUF;
typedef struct WSAData {
        WORD                    wVersion;
        WORD                    wHighVersion;
#ifdef _WIN64
        unsigned short          iMaxSockets;
        unsigned short          iMaxUdpDg;
        char FAR *              lpVendorInfo;
        char                    szDescription[WSADESCRIPTION_LEN+1];
        char                    szSystemStatus[WSASYS_STATUS_LEN+1];
#else
        char                    szDescription[WSADESCRIPTION_LEN+1];
        char                    szSystemStatus[WSASYS_STATUS_LEN+1];
        unsigned short          iMaxSockets;
        unsigned short          iMaxUdpDg;
        char FAR *              lpVendorInfo;
#endif
} WSADATA, FAR * LPWSADATA;//其实q个l构不需要怎么了解Q因为它在用的很,是在调用WSAStartup才用C?/font>

/*
 * Address families.
 */
#define AF_UNSPEC       0               /* unspecified */
/*
 * Although  AF_UNSPEC  is  defined for backwards compatibility, using
 * AF_UNSPEC for the "af" parameter when creating a socket is STRONGLY
 * DISCOURAGED.    The  interpretation  of  the  "protocol"  parameter
 * depends  on the actual address family chosen.  As environments grow
 * to  include  more  and  more  address families that use overlapping
 * protocol  values  there  is  more  and  more  chance of choosing an
 * undesired address family when AF_UNSPEC is used.
 */
#define AF_UNIX         1               /* local to host (pipes, portals) */
#define AF_INET         2               /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK      3               /* arpanet imp addresses */
#define AF_PUP          4               /* pup protocols: e.g. BSP */
#define AF_CHAOS        5               /* mit CHAOS protocols */
#define AF_NS           6               /* XEROX NS protocols */
#define AF_IPX          AF_NS           /* IPX protocols: IPX, SPX, etc. */
#define AF_ISO          7               /* ISO protocols */
#define AF_OSI          AF_ISO          /* OSI is ISO */
#define AF_ECMA         8               /* european computer manufacturers */
#define AF_DATAKIT      9               /* datakit protocols */
#define AF_CCITT        10              /* CCITT protocols, X.25 etc */
#define AF_SNA          11              /* IBM SNA */
#define AF_DECnet       12              /* DECnet */
#define AF_DLI          13              /* Direct data link interface */
#define AF_LAT          14              /* LAT */
#define AF_HYLINK       15              /* NSC Hyperchannel */
#define AF_APPLETALK    16              /* AppleTalk */
#define AF_NETBIOS      17              /* NetBios-style addresses */
#define AF_VOICEVIEW    18              /* VoiceView */
#define AF_FIREFOX      19              /* Protocols from Firefox */
#define AF_UNKNOWN1     20              /* Somebody is using this! */
#define AF_BAN          21              /* Banyan */
#define AF_ATM          22              /* Native ATM Services */
#define AF_INET6        23              /* Internetwork Version 6 */
#define AF_CLUSTER      24              /* Microsoft Wolfpack */
#define AF_12844        25              /* IEEE 1284.4 WG AF */
#define AF_IRDA         26              /* IrDA */
#define AF_NETDES       28              /* Network Designers OSI & gateway
                                           enabled protocols */
#define AF_TCNPROCESS   29
#define AF_TCNMESSAGE   30
#define AF_ICLFXBM      31

#define AF_MAX          32

/*
 * Protocol families, same as address families for now.
 */
#define PF_UNSPEC       AF_UNSPEC
#define PF_UNIX         AF_UNIX
#define PF_INET         AF_INET
#define PF_IMPLINK      AF_IMPLINK
#define PF_PUP          AF_PUP
#define PF_CHAOS        AF_CHAOS
#define PF_NS           AF_NS
#define PF_IPX          AF_IPX
#define PF_ISO          AF_ISO
#define PF_OSI          AF_OSI
#define PF_ECMA         AF_ECMA
#define PF_DATAKIT      AF_DATAKIT
#define PF_CCITT        AF_CCITT
#define PF_SNA          AF_SNA
#define PF_DECnet       AF_DECnet
#define PF_DLI          AF_DLI
#define PF_LAT          AF_LAT
#define PF_HYLINK       AF_HYLINK
#define PF_APPLETALK    AF_APPLETALK
#define PF_VOICEVIEW    AF_VOICEVIEW
#define PF_FIREFOX      AF_FIREFOX
#define PF_UNKNOWN1     AF_UNKNOWN1
#define PF_BAN          AF_BAN
#define PF_ATM          AF_ATM
#define PF_INET6        AF_INET6

#define PF_MAX          AF_MAX


下面q些函数属于基本常用函数Q下ơ学?br />u_long htonl(u_long hostlong)
u_short htons(u_short hostshort)
u_long ntohl(u_long netlong)
u_short ntohs(u_short netshort)
unsigned long inet_addr(const char* cp);
int getpeername(SOCKET s,struct sockaddr* name,int* namelen);
int getsockname(SOCKET s,struct sockaddr* name,int* namelen);
char* FAR inet_ntoa(struct in_addr in);
struct HOSTENT* FAR gethostbyaddr(const char* addr,int len,int type);
struct hostent* FAR gethostbyname(const char* name);
int gethostname(char* name,int namelen);
int WSAGetLastError(void);
int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
int ioctlsocket(SOCKET s,long cmd,u_long* argp);
int listen(SOCKET s,int backlog);
SOCKET accept(SOCKET s,struct sockaddr* addr,int* addrlen);
int send(SOCKET s,const char* buf,int len,int flags);
int recv(SOCKET s,char* buf,int len,int flags);



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=541158



]]>
Socket学习W记之二Q常用基本函敎ͼ http://www.shnenglu.com/tx7do/articles/5955.html杨粼?/dc:creator>杨粼?/author>Thu, 20 Apr 2006 09:27:00 GMThttp://www.shnenglu.com/tx7do/articles/5955.htmlhttp://www.shnenglu.com/tx7do/comments/5955.htmlhttp://www.shnenglu.com/tx7do/articles/5955.html#Feedback0http://www.shnenglu.com/tx7do/comments/commentRss/5955.htmlhttp://www.shnenglu.com/tx7do/services/trackbacks/5955.html

函数Q?br />u_long htonl(u_long hostlong)
u_short htons(u_short hostshort)
u_long ntohl(u_long netlong)
u_short ntohs(u_short netshort)

q上面四个函数类|功能怼Q都用来转换数据格式。用来实现处理器中shortQlong数据cd与网l中的{换。在|络中传输均以字节ؓ单位Q除了bit外就是最的单位了)。一个short占两字节Q一个long占四个字节。一个short从一台机子传到另外一台机子上要能够还原,则必ȝ一规定高低字节序。在TCP/IP协议规范中short的高位在低字节,低位在高字节。这与有些处理器中或者系l中表示不一栗例如在windows中:
 unsigned short hs = 0x0102;
 unsigned short ns = htons( hs );
 printf( "0x%04x",ns);//ns:0x0201
所以对于网l端口等数据在用前必须q行l一Q例?br />unsigned short port = 2088Q?br />m_sockaddr.sin_port = htons( port );
{等。这四个函数Q我开始不知道Z么取q些名字LC住,后来x白了
htons表示host to net shortQntohs表示net to host short
htonl表示host to net longQntohl表示net to host long
q样不需要刻意去C明白了?/p>

unsigned long inet_addr(const char* cp);
char* FAR inet_ntoa(struct in_addr in);

q两个函数用来把表示ip地址的字W串Q如Q?02.114.14.12Q跟表示ip的long或者结构之间{换?br />inet_addr得到的是已经l一字节序的,可以直接赋值给in_addr里的s_adrQ例如:
 char *pHost = "202.114.14.12"
 m_sockaddr.sin_addr.s_addr = inet_addr( pHost );

int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
加蝲winsock库。返?表示成功Q非0表示错误。第一个参数是版本P现在最高版本是2.2版,不过Win CE好像只支?.1版,高位字节表示副版本号Q低位字节表C高版本P所以这里一般就?x0202或?x0101或者用宏定义MAKEWORD(2,2)或者MAKEWORD(1,1)Q第二个参数是一个与winsock库信息有关的l构Q一把不用去它。在使用winsock前,都必d载,一般在E序初始化时候做q个事情。一般用如下:
 WSADATA data;
 if ( WSAStartup(0x0202,&data) != 0 )
 {
  printf("error id: %d",GetLastError());
 }
上面?font color="#ff6600">GetLastError()
是用非帔RJ的函数。很多函数的q回值得意义都是表示函数执行是否出错。当winsock的函数发生错误时Q用GetLastError()可以得到最后一ơ发生错误的错误受在.Net中有个工P查找错误Q输入错误号Q得到错误信息?/p>

int gethostname(char* name,int namelen);
获取L名。输入参Cؓ~冲区地址和大?br />struct hostent* FAR gethostbyname(const char* name);
׃机名得到L信息Q可以用来解析域名。需要注意的是MSDN中的一D话“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”这说明了一般用法的时候,要把数据拯出来Q看看下面代码:
 char   name[255];
 PHOSTENT  phostinfo;
 PHOSTENT  phostinfo1;
 WSADATA data;
 struct in_addr** addrPtr;
 struct in_addr** addrPtr1;

 if ( WSAStartup(0x0202,&data) != 0 )
 {
  printf("error id: %d",GetLastError());
 }

 if( gethostname ( name, sizeof(name)) == 0)
 {
  printf("%s",name);
  if((phostinfo = gethostbyname(name)) != NULL)
  {
   for (addrPtr = (struct in_addr **)phostinfo->h_addr_list;*addrPtr;addrPtr++)
   {//昄我机子的ip
    printf("%s\n", inet_ntoa(**addrPtr));
   }
  }
  else
   printf("error id : %d",GetLastError());
 }
 else
 {
  printf("error id :%d",GetLastError());
 }

 if((phostinfo1 = gethostbyname("bbs.whnet.edu.cn")) != NULL)
 {
  for (addrPtr1 = (struct in_addr **)phostinfo->h_addr_list;*addrPtr1;addrPtr1++)
  {//昄bbs.whnet.edu.cn的ipQ?02.114.0.248
   printf("%s\n", inet_ntoa(**addrPtr1));
  }
 }
 else
  printf("error id : %d",GetLastError());

 for (addrPtr = (struct in_addr **)phostinfo->h_addr_list;*addrPtr;addrPtr++)
 {//在这里显C的是bbs.whnet.edu.cn的ipQ?02.114.0.248Q不是我机子的ip
  printf("%s\n", inet_ntoa(**addrPtr));
 }

struct HOSTENT* FAR gethostbyaddr(const char* addr,int len,int type);
Ҏip地址得到L信息。这里的ip必须是网l字节顺序的。示例代码:
 PHOSTENT phostinfo2;
 unsigned long ip = inet_addr("127.0.0.1");
 if ( (phostinfo2 = gethostbyaddr((char*)&ip,sizeof(ip),AF_INET)) != NULL)
 {//昄localhost
  printf("host name : %s",phostinfo2->h_name );
 }
 else
  printf("error id : %d",GetLastError());

int getsockname(SOCKET s,struct sockaddr* name,int* namelen);
q个函数用来的得到socket的本地地址Q但是前提是socket必须已经bind或者已l是q接上的。如果socket不是面向q接的话Q比如udpQ那得socket上有数据才行?br />int getpeername(SOCKET s,struct sockaddr* name,int* namelen);
q个函数用来得到socket那一边上的地址Q显然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>

至于bind,listen,accept,recv,send{后面学select模型的时候再仔细研究?/p>

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=551760



杨粼?/a> 2006-04-20 17:27 发表评论
]]>Windows I/O模型、同?异步、阻?非阻?/title><link>http://www.shnenglu.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.shnenglu.com/tx7do/articles/5954.html</guid><wfw:comment>http://www.shnenglu.com/tx7do/comments/5954.html</wfw:comment><comments>http://www.shnenglu.com/tx7do/articles/5954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/tx7do/comments/commentRss/5954.html</wfw:commentRss><trackback:ping>http://www.shnenglu.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, 宋体">  所谓同步,是在发Z个功能调用时Q在没有得到l果之前Q该调用׃q回。按照这个定义,其实l大多数函数都是同步调用Q例如sin, isdigit{)。但是一般而言Q我们在说同步、异步的时候,Ҏ那些需要其他部件协作或者需要一定时间完成的d。最常见的例子就?SendMessage。该函数发送一个消息给某个H口Q在Ҏ处理完消息之前,q个函数不返回。当Ҏ处理完毕以后Q该函数才把消息处理函数所q回?LRESULTD回给调用者?/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, 宋体">  异步的概念和同步相对。当一个异步过E调用发出后Q调用者不能立d到结果。实际处理这个调用的部g在完成后Q通过状态、通知和回调来通知调用者。以 CAsycSocketcMؓ例(注意QCSocket从CAsyncSocketzQ但是v功能已经由异步{化ؓ同步Q,当一个客L通过调用 Connect函数发出一个连接请求后Q调用者线E立d以朝下运行。当q接真正建立h以后Qsocket底层会发送一个消息通知该对象。这里提到执?部g和调用者通过三种途径q回l果Q状态、通知和回调。可以用哪一U依赖于执行部g的实玎ͼ除非执行部g提供多种选择Q否则不受调用者控制。如果执行部 件用状态来通知Q那么调用者就需要每隔一定时间检查一ơ,效率很低(有些初学多线E编E的人,dƢ用一个@环去查某个变量的|q其实是一U很严重 的错误)。如果是使用通知的方式,效率则很高,因ؓ执行部g几乎不需要做额外的操作。至于回调函敎ͼ其实和通知没太多区别?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>d</strong><br style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">  d调用是指调用l果q回之前Q当前线E会被挂赗函数只有在得到l果之后才会q回。有Z怼把阻塞调用和同步调用{同hQ实际上他是不同的。对于同 步调用来_很多时候当前线E还是激zȝQ只是从逻辑上当前函数没有返回而已。例如,我们在CSocket中调用Receive函数Q如果缓冲区中没有数 据,q个函数׃一直等待,直到有数据才q回。而此Ӟ当前U程q会l箋处理各种各样的消息。如果主H口和调用函数在同一个线E中Q除非你在特D的界面?作函C调用Q其实主界面q是应该可以h。socket接收数据的另外一个函数recv则是一个阻塞调用的例子。当socket工作在阻塞模式的时候, 如果没有数据的情况下调用该函敎ͼ则当前线E就会被挂vQ直到有数据为止?/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, 宋体">  非阻塞和d的概늛对应Q指在不能立d到结果之前,该函C会阻塞当前线E,而会立刻q回?/p> <p style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">  对象的阻塞模式和d函数调用<br style="LINE-HEIGHT: 22px; FONT-FAMILY: arial, sans-serif, 宋体">  对象是否处于d模式和函数是不是d调用有很强的相关性,但是q不是一一对应的。阻塞对象上可以有非d的调用方式,我们可以通过一定的API去轮询状 态,在适当的时候调用阻塞函敎ͼ可以避免阻塞。而对于非d对象Q调用特D的函数也可以进入阻塞调用。函数select是q样的一个例子?/p> <p></span></span></span></span></span></span><br>在Winsock中实现异步的Ҏ有很多,Winsock的IO模型有下面六U?br><strong>    一Qselect模型<br>    二:WSAAsyncSelect模型<br>    三:WSAEventSelect模型<br>    四:Overlapped I/O 事g通知模型<br>    五:Overlapped I/O 完成例程模型<br>    六:IOCP模型</strong><br>从一到六来高U,来高效,实现来复杂?br><br><br>曑֜|上看到一些比ȝ来很好的说明q些模型Q在q里引用一下?br>老陈有一个在外地工作的女儿,不能l常回来Q老陈和她通过信g联系。他们的信会被邮递员投递到他们的信里?br><strong>一Qselect模型</strong></p> <p>老陈非常想看到女儿的信。以至于他每?0分钟׃楼检查信,看是否有奛_的信~~~~~<br>在这U情况下Q?#8220;下楼查信?#8221;然后回到g耽误了老陈太多的时_以至于老陈无法做其他工作?/p> <p><strong>二:WSAAsyncSelect模型</strong></p> <p>后来Q老陈使用了微软公司的新式信箱。这U信非常先q,一旦信里有新的信Ӟ盖茨׃l老陈打电话:喂,大爷Q你有新的信件了Q从此,老陈再也不必频繁上下楼检查信׃Q牙也不gQ你瞅准了,蓝天......不是Q微软~~~~~~~~</p> <p><strong>三:WSAEventSelect模型</strong></p> <p>后来Q微软的信箱非常畅销Q购买微软信qZ百万计数......以至于盖茨每?4时l客h电话Q篏得腰酸背痛,喝蚁力神都不好~~~~~~<br>微Y改进了他们的信箱Q在客户的家中添加一个附加装|,q个装置会监视客L信箱Q每当新的信件来_此装|会发出“C件到?#8221;壎ͼ提醒老陈L信。盖茨终于可以睡觉了?/p> <p><strong>四:Overlapped I/O 事g通知模型</strong></p> <p>后来Q微软通过调查发现Q老陈不喜Ƣ上下楼收发信gQ因Z下楼其实很浪Ҏ间。于是微软再ơ改q他们的信箱。新式的信箱采用了更为先q的技术,只要用户告诉微Y自己的家在几楼几P新式信箱会把信g直接传送到用户的家中,然后告诉用户Q你的信件已l放C的家中了Q老陈很高_因ؓ他不必再亲自收发信g了!</p> <p><strong>五:Overlapped I/O 完成例程模型</strong></p> <p>老陈接收到新的信件后Q一般的E序是:打开信封----掏出信纸----阅读信g----回复信g......Zq一步减ȝ戯担,微Y又开发了一U新的技术:用户只要告诉微Y对信件的操作步骤Q微软信将按照q些步骤d理信Ӟ不再需要用户亲自拆?阅读/回复了!老陈l于q上了小资生z!</p> <p><strong>六:IOCP模型</strong></p> <p>微Y信箱g很完,老陈也很满意。但是在一些大公司情况却完全不同!q些大公司有C万计的信,每秒钟都有数以百计的信g需要处理,以至于微软信q常因负药转而崩溃!需要重新启动!微Y不得不出杀手锏......<br>微Yl每个大公司z了一名名?#8220;Completion Port”的超U机器hQ让q个机器人去处理那些信gQ?/p> <p><br>其实Q上面每U模型都有优点,要根据程序需求而适当选择合适的模型Q前面三U模型效率已l比较高Q实现v来难道不大,很多一般的|络E序都采用前三种模型Q只有对|络要求特别高的一些服务器才会考虑用后面的那些模型。MFC中的CAsyncSocketcd是用的WSAAsyncSelect模型Q电驴中也是用的q种Q不q在L对应socket的时候进行了优化Q查找更快,在GridCast中采用的是WSAEventSelect模型Q等待?/p> <img src ="http://www.shnenglu.com/tx7do/aggbug/5954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/tx7do/" target="_blank">杨粼?/a> 2006-04-20 17:25 <a href="http://www.shnenglu.com/tx7do/articles/5954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何~写Linux下的客户?服务器Y?/title><link>http://www.shnenglu.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.shnenglu.com/tx7do/articles/5952.html</guid><wfw:comment>http://www.shnenglu.com/tx7do/comments/5952.html</wfw:comment><comments>http://www.shnenglu.com/tx7do/articles/5952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/tx7do/comments/commentRss/5952.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/tx7do/services/trackbacks/5952.html</trackback:ping><description><![CDATA[   Linux以其源代码公开d于世Qƈ以其E_性和可靠性雄霸操作系l领域,在网l应用技术方面用得更加q泛。很久以来它是Windows的重要对手之一。随着|络时代的来_Linux的这U优势已变得更加H出。本文将如何在Linux环境下利用Socket实现客户?服务器通信?<br />随着|络技术的发展Q网l结构已从过ȝL/l端型、对{型发展到现在广Z用的客户?服务器型。客h/服务器模型应用十分广泛,在Internet上WWWQE-mailQFTP{都是基于这U模型的。在面向q接的通信模式下,服务器打开监听端口Q监听网l上其它客户机向该服务器发出的连接请求,当收C个请求信h与该客户机徏立一个连接,之后两者进行交互式的通信。具体步骤可q样l织Q?<br /><br />服务器: <br />1.打开一个已知的监听端口Q如smtp?5、pop3?10、ftp?1、telnet?3{?<br />2.在监听端口上监听客户机的q接hQ如果有客户求连接则建立一个连接线路?<br />3.在连接线路上与客h通信?<br />4.通信完毕后关闭连接线路ƈl箋监听客户机的q接h?<br /><br />客户机: <br />1.向指定的服务器主机及端口发出q接h?<br />2.当服务器建立q接U\后与服务器进行通信?<br />3.通信完毕后关闭连接线路?<br /><br />Linux的许多特性都非常有助于网l程序设计:首先Linux拥有POSIX.1标准库函敎ͼsocket()、bind()、listen()q几个库函数可以非常方便地实现服务器/客户机模型,有关q几个库函数的用说明将在后边介l。其ơLinux的进E管理也非常W合服务器的工作原理Q所谓进E就是程序在内存中运行时的状态,可以说进E是动态的E序。在q行着Linux操作pȝ的计机中,每一个进E都有一个创建它的父q程Q而且它也能创建多个子q程。在服务器端我们可以用父q程ȝ听客h的连接请求,当有客户机的q接h时父q程创徏一个子q程d立连接线路ƈ与客h通信Q而它本n可l监听其它客h的连接请求,q样可避免当有一个客h与服务器建立q接后服务器׃能再与其它客h通信的问题。Linux的另一个特性是它秉承了UNIX讑֤无关性这一优秀特征Q即它通过文g描述W实Cl一的设备接口,盘、显C终端、音频设备、打印设备甚至网l通信都用统一的I/O调用。这三个Ҏ将使Linux下的|络E序设计变得易如反掌。上qC个特性的l合利用是q篇文章所要讲q的真谛所在。下边的客户?服务器实现过E可以说明一二,注意与上文所q步骤的不同?<br /><br />服务器: <br />1.打开一个已知的监听端口?<br />2.在监听端口上监听客户机的q接hQ当有一客户求连接时建立q接U\q返回通信文g描述W?<br />4.父进E创Z子进E,父进E关闭通信文g描述Wƈl箋监听端口上的客户接请求?<br />3.子进E通过通信文g描述W与客户行通信Q通信l束后终止子q程q关闭通信文g描述W?<br /><br />客户机: <br />1.向指定的服务器主机及端口发出q接hQ请求成功将q回通信文g描述W?<br />2.通过通信文g描述W与服务器进行通信?<br />3.通信完毕后关闭通信文g描述W?<br /><br /><br />Linux的以下几个库函数是网l程序设计的核心部分Q它们分别是Q?<br />(1)socket <br />调用方式Q?<br />#include <br />#include <br /><br />int socket(int domain,int type,int protocol); <br /><br />要说明: <br />此函Cؓ通信创徏一个端口,正常调用返回一个文件描q符Q错误调用将q回-1。domain参数有两U选择QAF_UNIX与AF_INETQ其中AF_INET为Internet通信协议。type参数也有两种选择QSOCK_STREAM用于TCPQSOCK_DGRAM用于UDP。protocol参数通常?。可通过下列代码为基于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 />调用方式Q?<br />#include <br />#include <br /><br />int bind(int s,const struct sockaddr *address,size_t address_len); <br /><br />要说明: <br />bind英文含意是关联,捆绑。其目的是把socketq回的套接口端口与网l上的物理位|相兌?<br />bind正常调用q回0Q出错返?1。此函数有三个参敎ͼ其中s为socket调用q回的文件描q符Q?address讄了与|络上的物理位置相关的信息,它的cd是struct sockaddrQ但在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_INETQsin_port为端口号Q由于用不同字节顺序的机器必须作{换,故应使用宏命令htons(host to network short)来{换端口号Qsin_addr置为INADDR_ANY。这三个D|完成后*address参数才有意义。在~写代码Ӟ应先讄*address参数内部各成员变量的|再调用bind?<br /><br />(3)listen <br />调用方式Q?<br />#include <br />#include <br /><br />int listen(int s,int backlog); <br /><br />要说明: <br />本函Csocket端口能够接受从客h来的q接hQ正常调用返?Q出错返?1?<br />s参数为socket产生的文件描q符Qbacklog为所能接受客h的最大数目?<br />socketQbindQlisten 三个函数的综合调用最l在服务器上产生一个能接受客户求的监听文g描述Ws?<br /><br />(4)accept <br />调用方式Q?<br />#include <br />#include <br /><br />int accept(int s,struct sockaddr *address,int *address_len); <br /><br />要说明: <br />当有客户机发接请求时Q此函数初始化这个连接。正常调用返回与客户机通信的通信文g描述W,出错q回-1。参数s为socket调用q回的文件描q符Qaddress用来存储客h的信息,此信息由accept填入Q当与客hq接Ӟ客户机的地址与端口将填到此处。address_len是客h地址长度的字节数Q也由accept填入?<br /><br />(5)connect <br />调用方式Q?<br />#include <br />#include <br /><br />int connect(int s,struct sockaddr *address,size_t address_len); <br /><br />要说明: <br />客户用socket建立传输端口后,调用connect来徏立与q程服务器相q的q接U\?<br />此函数的参数调用同bind?<br /><br />(6)inet_addr <br />调用方式Q?<br />#include <br />#include <br />#include <br /><br />in_addr_t inet_addr(const char *addstring); <br /><br />要说明: <br />此函数将字符串addstring表示的网l地址Q如192.168.0.1Q{换成32位的|络字节序二q制|若成功返?2位二q制的网l字节序地址Q若出错q回 INADDR_NONE。INADDR_NONE?2位均?的|?55.255.255.255Q它是Internet的有限广播地址Q,故如果要转换的addstring?55.255.255.255Q函数调用将p|?<br /><br />(7)fork <br />调用方式Q?<br />#include <br />#include <br /><br /><br />pid_t fork(void); <br /><br />要说明: <br />fork的作用是拯父进E的内存映象来创建子q程Q两个进E将接着fork后的指ol箋执行?事实上它q回两个q程控制P对于父进E它q回子进E的q程IDQ对于子q程它返??<br /><br />可用下边的代码调用forkQ?<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 />调用子进E? <br />} <br />else if(child>0){ <br />调用父进E? <br />} <br /><br /><br />以上介绍了网l编E的有关库函数的调用ҎQ下面D一个客h/服务器程序的例子具体说明如何设计网l程序。本例介l如何查看服务器上的旉和日期,׃daytime服务器的通用端口?3Q客hE序通过调用13L口对服务器上的时间和日期q行操作?<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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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">服务器程序伪代码如下Q?br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />打开daytime监听端口Q?br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />while(客户Z服务器成功连接——成功返回通信文g描述W? <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />{ <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />fork() <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />子进E: <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />{ <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />d当前旉Q?br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />当前时间写入通信文g描述W; <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />关闭通信文g描述W; <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />} <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />父进E: <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />关闭通信文g描述W; <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />} <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /></span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_343_1167_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />pid_t childpid; <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />time_t tick; <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_499_548_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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">&</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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_720_756_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_789_827_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_892_1154_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_922_958_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_983_1111_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.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">&</span><span style="COLOR: #000000">tick)); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />write(communfd,buf,strlen(buf)); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />close(communfd); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.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 src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />close(communfd); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />#include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_1314_1972_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_1409_1449_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_1502_1540_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_1667_1708_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.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">&</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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_1783_1822_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.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">></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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_1867_1941_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />close(communfd); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />exit(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">); <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"> <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /></span></div>用gcc~译两个源程序分别取名ؓserver和clientQ以根用戯n份运行服务器E序Q设服务器网l地址?92.168.0.1Q: <br />server & <br />然后q行客户机程序(设服务器|络地址?92.168.0.1Q: <br />client 192.168.0.1 <br />在客h上就会反映出服务器上当前的时间如QTue Feb 29 21:46:19 2000Q?<br /><br />以上E序代码在redhat 6.0上试验通过。在E序代码中有兛_函数snprintf、fputs、read、write、close的用法就不在q里说明了,如想了解q些库函数的调用Ҏ可到我的|页http://lzdx.yeah. net/pro_unix.htmlL找。在我的|页http://lzdx.yeah.net/pro_uici.html中有关于通用Internet接口QUICIQ专用库的介l,通用Internet接口QUICIQ利用Socket库函数提供了一个简化的独立于传输的接口Q它从整体上化了|络E序设计q程。有兴趣的h可到那里ȝ看。最后祝愿我们每个h都能~写q|络E序?img src ="http://www.shnenglu.com/tx7do/aggbug/5952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/tx7do/" target="_blank">杨粼?/a> 2006-04-20 17:19 <a href="http://www.shnenglu.com/tx7do/articles/5952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>unix下编写socketE序的一般步?/title><link>http://www.shnenglu.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.shnenglu.com/tx7do/articles/5951.html</guid><wfw:comment>http://www.shnenglu.com/tx7do/comments/5951.html</wfw:comment><comments>http://www.shnenglu.com/tx7do/articles/5951.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/tx7do/comments/commentRss/5951.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/tx7do/services/trackbacks/5951.html</trackback:ping><description><![CDATA[在unix下写socketE序可能是最方便Q你只要掌握其一般步骤,可以松的写出面向传输层的应用?<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指所用的传输cdQ可以ؓSOCK_STERAM(面向q接的TCP),和SOCK_DGRAM(面向无连接的udp)<br /><br />  int bind(int s,const struct sockaddr *address,size_t address_len);<br /><br />  s为socketq回的文件描q符<br /><br />  address为协议族名称和其他信?br /><br />  具体l构为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为容许的h数目</font><br /><br />  int accept(int s,struct sockaddr *address,int *address_len);<br /><br />  <font color="#008000">q里的前两个参数同上</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">q里的参数意义同bind</font><br /><br />  2.<b>理解建立E序的一般调用过E?/b><br /><br />  要徏立一个处理连接的服务器端E序Q首先要调用socket函数创徏一个socket,q回一个文件句柄fdQ以后对它的操作就象对普通文件设备一栯写?br /><br />  ׃是服务器端必d一个断口进行监听其他机器的h,所以接下去调用bind函数Q传入刚才的fd,定义好地址和端口,׃是要接受来自Mhost的连接所以应讲sin_addr赋ؓINADDR_ANY,portZ所讑֮的端口?br /><br />  <b>注意</b>Q这里的地址和端口是|络字节序Q所以要调用htonl,htons完成L字节序<br />到网l字节的转变<br /><br />  接下来就是监听listen,调用accept接受来自客户端的hQaccpetq回q接后的文g描述W,你就可以用它q行收发信息Q对应于read,write)q样的一个过E就是socket->bind->listen->accpet->Read,write<br />而对于客L则是socket->connect->read,write <p><span id="4o2ue4e" class="txt">3.<b>一个完整的E序</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.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">  #include <br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />  #include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" />  #include <br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_98_1277_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000"> pid;<br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> ret;<br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> len;<br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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">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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_274_327_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />     }</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.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">&</span><span style="COLOR: #000000">myaddr,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(myaddr));<br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (ret</span><span style="COLOR: #000000"><</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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_527_578_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />     }</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_656_1268_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.shnenglu.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">&</span><span style="COLOR: #000000">cliaddr,</span><span style="COLOR: #000000">&</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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.com/images/dot.gif" /></span><span id="Codehighlighter1_777_837_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">continue</span><span style="COLOR: #000000">;<br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.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.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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">子进E?/span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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">子进E进行其他的操作</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />           close(clifd);<br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />           exit(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />           </span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br /><img src="http://www.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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.shnenglu.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">父进E?/span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />           close(clifd);<br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" />           </span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />       }</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />      }</span></span><span style="COLOR: #000000"><br /><img src="http://www.shnenglu.com/images/OutliningIndicators/None.gif" align="top" /></span></div>  4.<b>E序说明</b><br /><br />  该程序的功能是监?888端口的连?Ҏ有的?888端口的连接显C出地址和对方的端口可E序在sco unix下调试通过Q在其他unix和linuxq_h意inet_ntoa,htons函数所应在的头文g的名U?br /><br />  同时该程序用Cq发的观点,因ؓaccept,read,write均ؓd(block)的函敎ͼ一旦进Eblock不能处理其他请求,所以用主进E进行listen,由子q程q行负责对客L传输数据. <br /><br />  你可以在同一台unix机器用telnet localhost 8888q行观察E序会输出connect from 127.0.0.1 xxxx<br /></sys></sys><img src ="http://www.shnenglu.com/tx7do/aggbug/5951.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/tx7do/" target="_blank">杨粼?/a> 2006-04-20 17:17 <a href="http://www.shnenglu.com/tx7do/articles/5951.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP/IP~程实现q程文g传输http://www.shnenglu.com/tx7do/articles/5950.html杨粼?/dc:creator>杨粼?/author>Thu, 20 Apr 2006 09:16:00 GMThttp://www.shnenglu.com/tx7do/articles/5950.htmlhttp://www.shnenglu.com/tx7do/comments/5950.htmlhttp://www.shnenglu.com/tx7do/articles/5950.html#Feedback0http://www.shnenglu.com/tx7do/comments/commentRss/5950.htmlhttp://www.shnenglu.com/tx7do/services/trackbacks/5950.html
TCP/IP~程实现q程文g传输
  
    在TCP/IP|络l构中,Z保证|络安全Q网lh员往往需要在路由器上d防火墙,止非法用户用ftp{安全危完大的TCP/IP协议讉KL。而有时系l维护h员需要用ftp一些文件从中心机房L传到前端|点L上,比如应用E序的替换升U。如果每ơ传输文件时都要打开防火墙,未免昑־有些J琐Q要是在自己的应用程序中增加一个专门的文g传输模块Q那是十分愉快的事情?
 
  UNIX|络E序设计一般都采用套接?socket)pȝ调用。针对目前十分流行的客户/服务器模式,其程序编写步骤如下:
  1.Socketpȝ调用
  Zq行|络I/OQ服务器和客h两端的UNIXq程要做的第一件事是调用socket()pȝ调用Q徏立Y插Q指明合适的通讯协议。格式ؓQ?
  Qinclude<sys/types.h>
  Qinclude<sys/socket.h>
  int socket(int family,int type,int protocol)
  其中Q?1)family指明套节字族Q其值包括:
  AF_UNIX   (UNIX内部协议?
  AF_INET   (Iternet协议)
  AF_NS (XeroxNs协议QTCP/IP~程取该?
  AF_IMPLINK  (IMP链接?
  (2)type 指明套接字类型,取值有Q?
  SOCK_STREAM     (套接字)
  SOCK_DGRAM     (数据报套接字)
  SOCK_RAW      (原始套接?
  SOCK_SEQPACKET   (定序分组套接?
  一般情况下Q前两个参数的组合就可以军_所使用的协议,q时W三个参数被|ؓ0Q如果第一个参CؓAF_INETQ第二个参数选SOCK_STREAMQ则使用的协议ؓTCPQ第二个参数选SOCK_DGRAMQ则使用的协议ؓUDPQ当W二个参数选SOCK_RAWӞ使用的协议ؓIP。值得指出的是q不是所有的族和cd的组合都是合法的Q具体请查阅相关资料。该pȝ调用若成功则q回一个类似文件描q符Q成为套节字描述字,可以像文件描q符那样用read和write对其q行I/O操作。当一个进E用完该Y插Ӟ需用close(<描述W?gt;关闭(具体见后面内??
  2.服务器端Bindpȝ调用
  软插座创建时q没有与M地址相关联,必须用bind()pȝ调用为其建立地址联系。其格式为:
  Qinclude<sys/types.h>
  Qinclude<sys/socket.h>
  int bind(int socketfd,struct sockaddr_in Qlocaladdr,sizeof(localaddr));
  其中Q?1)W一个参数socketfd是前步socket()pȝ调用q回的套节字描述W?
  (2)W二个参数被捆向本地地址的一U结构,该结构在sys/netinet/in.h中定义:
  struct sockaddr_in{
   short sin_family;/Qsocket()pȝ调用的协议族如AF_INETQ?
   u_short sin_port;/Q网l字节次序Ş式的端口LQ?
   struct in_addr sin_addr;/Q网l字节次序Ş式的|络地址Q?
   char sin_zero[8];
  }
  一台机器上的每个网l程序用一个各自独立的端口LQ例如:telnetE序使用端口?3Q而ftp文g传输E序使用端口?1。我们在设计应用E序Ӟ端口L可以由getservbyname()函数?etc/services库文件中获取Q也可以由htons (int portnum)函数Q意正整数转换为网l字节次序Ş式来得到Q有些版本的UNIX操作pȝ则规?024以下的端口号码只可被用户使用Q普通用L序用的端口L只限?025?2767之间。网l地址可以由gethostbyname(charQhostname)函数得到(该函数和getservbyname()一样都以网l字节次序Ş式返回所有在他们l构中的数据)Q参数hostname?etc/hosts文g中某一|络地址所对应的机器名。该函数q回一个类型ؓhostent的结构指针,hostentl构在netdb.h中定义:
  struct hostent{
   char Qh_name;
   char Q*h_aliases;
   int h_addrtype;
   int h_length;  /Q地址长度Q?
   char Q*h_addr_list;
   Qdefine h_addr h_addr_list[0];/Q地址Q?
  }
  (3)W三个参CؓW二个结构参数的长度Q如果调用成功,bindq回0Q否则将q回Q?q设|errno?
  3.服务器端pȝ调用listenQ服务器愿意接受连?
  格式Qint listen(int socketfd,int backlong)
  它通常在socket和bind调用后在accept调用前执行。第二个参数指明在等待服务器执行accept调用时系l可以排队多个q接要求。此参数常指定ؓ5Q也是目前允许的最大倹{?
  4.服务器调用accept,以等待客h调用connectq行q接。格式如下:
  int newsocket=(int socketfd,struct sockaddr_in Qpeer,intQaddrlen);
  该调用取得队列上的第一个连接请求ƈ建立一个具有与sockfd相同Ҏ的套节字。如果没有等待的q接hQ此调用d调用者直Cq接h到达。连接成功后Q该调用用对端的地址l构和地址长度填充参数peer和addlenQ如果对客户端的地址信息不感兴趣Q这两个参数?代替?
  5.客户端调用connect()与服务器建立q接。格式ؓQ?
  connect(int socketfd,struct sockaddr_in Qservsddr,int addrlen)
  客户端取得套接字描述W后Q用该调用徏立与服务器的q接Q参数socketfd为socket()pȝ调用q回的套节字描述W,W二和第三个参数是指向目的地址的结构及以字节计量的目的地址的长?q里目的地址应ؓ服务器地址)。调用成功返?Q否则将q回Q?q设|errno?
  6.通过软插座发送数?
  一旦徏立连接,可以用pȝ调用read和write像普通文仉样向|络上发送和接受数据。Read接受三个参数Q一个是套节字描q符Q一个ؓ数据被填入的缓冲区Q还有一个整数指明要ȝ字节敎ͼ它返回实际读入的字节敎ͼ出错时返回-1Q遇到文件尾则返?。Write也接受三个参敎ͼ一个是套节字描q符Q一个ؓ指向需要发送数据的~冲区,q有一个整数指明要写入文g的字节个敎ͼ它返回实际写入的字节敎ͼ出错时返回-1。当Ӟ也可以调用send和recv来对套节字进行读写,其调用与基本的read和writepȝ调用怼Q只是多了一个发送方式参数?
  7.退出程序时Q应按正常方式关闭套节字。格式如下:
  int close(socketfd)
  前面介绍了UNIX客户/服务器模式网l编E的基本思\和步骤。值得指出的是socket~程所涉及的系l调用不属于基本pȝ调用范围Q其函数原Ş在libsocket.a文g中,因此Q在用cc命o对原E序q行~译旉要带Qlsocket选项?
  现在Q我们可以针Ҏ章开头提出的问题着手进行编E了。在囄的网l结构中Qؓ使中心机房的服务器能和网点上的客hq行通信Q需在服务器端添加通过路由????到客h的\由,两台客户Z必须d通过路由????到服务器的\由。在服务器的/etc/hosts文g中应该包含下面内容:
  1.1.1.1  server
  2.2.2.2  cli1
  2.2.2.3  cli2
  客户机的/etc/hosts文g中应该有本机地址信息和服务器的地址信息Q如cli1客户机的/etc/hosts文gQ?
  2.2.2.2  cli1
  1.1.1.1  server
  |络环境搭徏好后Q我们可以在服务器端~写fwq.cE序Q负责接受客h的连接请求,q将从源文g中读取的数据发送到客户机。客hE序khj.c向服务器发送连接请求,接收从服务器端发来的数据Qƈ接收到的数据写入目标文件。源E序如下Q?
/Q服务器源程序fwq.cQ?/span>/ 
Qinclude
<stdio.h> 
Qinclude
<sys/types.h> 
Qinclude
<sys/fcntl.h> 
Qinclude
<sys/socket.h> 
Qinclude
<sys/netinet/in.h> 
Qinclude
<netdb.h> 
Qinclude
<errno.h> 
main() 

  
char c,buf[1024],file[30]; 
  
int fromlen,source; 
  register 
int k,s,ns; 
  
struct sockaddr_in sin; 
  
struct hostent Qhp; 
  system(″clear?; 
  printf(″\n?; 
    
  printf(″\n\n\t\t输入要传输的文g名:?Q?br />  scanf(※Is?file); 
  
if ((source=open(file,O_RDONLY))<0)
   perror(x文g打开出错?Q?br />   exit(
1); 
  }
 
  printf(″\n\t\t在传送文ӞE候…?Q?br />  hp
=gethostbyname(″server?; 
  
if (hp==NULL)
   perror(‌回主机地址信息?/span>!!!?Q?br />   exit(2); 
  }
 
  s
=socket(AF_INET,SOCK_STREAM,0); 
  
if(s<0)
   perror(‌取SOCKET号失?/span>!!!?Q?br />   exit(3); 
  }
 
  sin.sin_family
=AF_INET; 
  sin.sin_port
=htons(1500);/Q用端?500Q?/span>/ 
  bcopy(hpQ?/span>>h_addr,Qsin.sin_addr,hpQ?/span>>h_length); 
  
if(bind(s,Qsin,sizeof(sin))<0)
   perror(″不能将服务器地址捆绑到SOCKET号上
!!!?Q?br />   colse(s); 
   exit(
4); 
  }
 
  
if(listen(sQ?/span>5)<0
   perror(″sever:listen?; 
   exit(
5); 
  }
 
while(1)
  
if((ns=accept(s,Qsin,Qfromlen))<0)
   perror(″sever:accept?Q?br />   exit(
6); 
  }
 
  lseek(source,OL,
0);/Q每ơ接受客hq接Q应用于读的源文g指针Ud文g_/ 
  write(ns,file,
sizeof(file))Q?/span>/Q发送文件名Q?/span>/ 
  
while((k=read(source,buf,sizeof(buf)))>0
   write(ns,buf,k); 
  printf(″\n\n\t\t传输完毕
!!!\n?; 
  close(ns); 
}
 
  close(source); 
  exit(
0); 
  
/Q客h源程序khj.cQ?/span>/ 
  Qinclude
<stdio.h> 
  Qinclude
<sys/types.h> 
  Qinclude
<sys/fcntl.h> 
  Qinclude
<sys/socket.h> 
  Qinclude
<sys/netinet/in.h> 
  Qinclude
<netdb.h> 
  Qinclude
<errno.h> 
  Qinclude 
<string.h> 
  main() 
  

   
char buf[1024],file[30]; 
   
char Qstrs=″\n\n\t\t正在接收文g※I 
   
int target; 
   register 
int k,s; 
   
struct sockaddr_in sin; 
   
struct hostent Qhp; 
   system(″clear?; 
   printf(″\n?; 
     
   hp
=gethostbyname(″server?; 
   
if(hp==NULL)
          perror(‌回服务器地址信息?/span>!!!?Q?br />    exit(1); 
   }
 
   s
=socket(AF_INETQSOCK_STREAM,0); 
   
if(s<0)
    perror(‌取SOCKET号失?/span>!!!?Q?br />    exit(2); 
   }
 
   sin.sin_family
=AF_INET; 
   sin.sin_port
=htons(1500);/Q端口号需与服务器E序使用的一_/ 
   bcopy(hpQ?/span>>h_addr,Qsin.sin_addr,hpQ?/span>>h_length); 
   printf(″\n\n\t\t正在与服务器q接…?Q?br />   
if(connect(s,Qsin,sizeof(sin),0)<0)
    perror(″不能与服务器连?/span>!!!?Q?br />    exit(3); 
   }
 
   
while((k=read(s,file,sizeof(file)))<=0/Q接收文件名Q?/span>/ 
   
if((target=open(file,o_WRONLY|O_CREAT|O_TRUNC,0644))<0)
    perror(″不能打开目标文g
!!?Q?br />    exit(4); 
  }
 
  strcat(strs,file); 
  strcat(strs,※IE候…?Q?br />  write(
1,strs,strlen(strs)); 
  
while((k=read(s,buf,sizeof(buf)))>0
   write(tatget,buf,k); 
  printf(″\n\n\t\t接收文g成功
!!!\n?; 
  close(s); 
  close(target); 
  }
 

  上述E序在Sco Unix System v3.2及Sco TCP/IP Rumtime环境下调试通过?br />

]]>
AF_UNIX 地址pdhttp://www.shnenglu.com/tx7do/articles/5949.html杨粼?/dc:creator>杨粼?/author>Thu, 20 Apr 2006 09:15:00 GMThttp://www.shnenglu.com/tx7do/articles/5949.htmlhttp://www.shnenglu.com/tx7do/comments/5949.htmlhttp://www.shnenglu.com/tx7do/articles/5949.html#Feedback0http://www.shnenglu.com/tx7do/comments/commentRss/5949.htmlhttp://www.shnenglu.com/tx7do/services/trackbacks/5949.htmlAF_UNIX 地址pdQ?AF_UNIX ?AF_UNIX_CCSID 地址pd的套接字Q可以是面向q接的(cd SOCK_STREAMQ,也可以是无连接的Q类?SOCK_DGRAMQ。两U类型都很可靠,原因是没有连接两个进E的外部通信函数?

UNIX 域数据报套接字的q行方式?UDP 数据报套接字有所不同。借助 UDP 数据报套接字Q客hE序׃必调?bind() 函数Q原因是pȝ会自动指定未使用的端口号。于是服务器可将数据报发送回该端口号。但是,使用 UNIX 域数据报套接字,pȝ不会自动指定客户机的路径名。因此,使用 UNIX 域数据报的所有客hE序必须调用 bind() 函数。在客户机的 bind() 上指定的_路径名就是传递至服务器的路径名。因此,如果客户机指定相对\径名Q即Qƈ非以 / 开头的全限定\径名Q,除非服务器以同一当前目录q行Q否则它不能向客h发送数据报?

应用E序可能Ҏ地址pd使用的示例\径名是 /tmp/myserver ?servers/thatserver。借助 servers/thatserverQ可使用q全限定(未指?/Q的路径名。这表示该项在文件系l层ơ结构中的位|应Ҏ当前工作目录定?

注意:
文gpȝ中的路径名是启用?NLS 的?

下图举例说明?AF_UNIX 地址pd的客hQ服务器关系。有兛_环境讄Z?AF_UNIX 地址pd的详l信息,参见套接字编E的先决条g?


在服务器和客h AF_UNIX 地址pdCZE序中用的套接字事件流? src=

套接字事件流Q?AF_UNIX 地址pd的服务器应用E序
CZQ?AF_UNIX 地址pd的服务器应用E序使用以下函数调用序列Q?

  1. socket() 函数q回表示端点的套接字描述W。该语句q标识将Ҏ套接字用带有流传输QSOCK_STREAMQ的 UNIX 地址pd。该函数q回表示端点的套接字描述W。还可?socketpair() 函数初始?UNIX 套接字?

    AF_UNIX ?AF_UNIX_CCSID 是支?socketpair() 函数的唯一地址pd?b>socketpair() 函数q回未命名的和已q接的套接字描述W?

  2. 在创建套接字描述W之后,bind() 函数获取套接字的唯一名称?

    UNIX 域套接字的名U空间由路径名组成。当套接字程序调?bind() 函数Ӟ会在文gpȝ目录中创ZV如果\径名已存在,?bind() p|。因此,UNIX 域套接字E序应L调用 unlink() 函数以在l束旉去该目录V?

  3. listen() 允许服务器接受入局客户接。在此示例中Q储备设|ؓ 10。这表示pȝ对 10 个入局q接h排队Q然后才开始拒l入局h?
  4. recv() 函数从客h应用E序接收数据。在此示例中Q我们知道客h发送超q?250 字节的数据。既然如此,可以?SO_RCVLOWAT 套接字选项指定在所?250 字节数据都到达之前不要唤?recv()?
  5. send() 函数数据回传至客户机?
  6. close() 函数关闭所有打开的套接字描述W?
  7. unlink() 函数从文件系l除?UNIX 路径名?

套接字事件流Q?AF_UNIX 地址pd的客h应用E序
CZQ?AF_UNIX 地址pd的客h应用E序使用以下函数调用序列Q?

  1. socket() 函数q回表示端点的套接字描述W。该语句q标识将Ҏ套接字用带有流传输QSOCK_STREAMQ的 UNIX 地址pd。该函数q回表示端点的套接字描述W。还可?socketpair() 函数初始?UNIX 套接字?

    AF_UNIX ?AF_UNIX_CCSID 是支?socketpair() 函数的唯一地址pd?b>socketpair() 函数q回未命名的和已q接的套接字描述W?

  2. 接收到套接字描述W后Q?connect() 函数来徏立与服务器的q接?
  3. send() 函数发送指定的 250 字节数据Q该数据是在服务器应用程序中使用 SO_RCVLOWAT 套接字选项指定的?
  4. recv() 函数一直@环,直到所?250 字节数据都到达ؓ止?
  5. close() 函数关闭所有打开的套接字描述W?


]]>
ɫۺϾþþþۺһ| ޵һAVվþþƷ˵AV | ޹뾫ƷŮ˾þþò| ޹ƷƬþ| ޹Ʒһþ| 97þþþ| һþ| ޾ƷŮþþ| vaþþþúݺ| ˾þþƷһ| þۺɫݺ| þþþþAŷAV| þþƷվ| Ʒݾþþþø | ƷѾþþþþþþ| þþƷһ| 99ƷȾþ| þþƷ77777| þþƷһԡ| 97þù޾Ʒ| þþƷ| ձƷþþĻ| ݺ޾þþþþۺ | ݾþþù| һAvëƬþþƷ| þþƷަvDz | ŷսþþþþþ| yy6080þ| ƷҹþøƬ| 91þø˾Ʒ| ŷƷ˿þþĻ| һþþ| ƷŮٸaѾþ| ɫۺϾþɫ| vaþþþ| ƷŮٸaѾþ| þþþƷҰ| ٸþþþþþþþ| þ99Ʒþþþþˮ| ɾþۺ777| AVþþþòվ|