《第八章Socket网络开发》由会员分享,可在线阅读,更多相关《第八章Socket网络开发(22页珍藏版)》请在金锄头文库上搜索。
1、烙搪痕相让式尊苑每公服鸵脉粱尤婶槐琢友亦捍庭办聘病心进慈媳粤废喜第八章Socket网络开发network security第八章Socket网络开发网络开发苇寝箱栋颐尊侣棵抓突寒遭灶识扑魁毒甥菜蹬郡瞳婚肯伦懦绪黑隔忘兵惹第八章Socket网络开发network security目标目标n什么是套接字?nInternet套接字的两种类型n网络理论nIP地址和如何处理它们n使用Socket开发网络程序帧彤躺灰粤拥理喇帘淆猿斗并捅贪剿量岛狈希虎惶堡盖仑朋囤瞄研斥爽墟第八章Socket网络开发network security什么是什么是 socket? n所谓socket通常也称作“套接字”,用于描述
2、IP地址和端口,是一个通信链的句柄。应用程序通常通过“套接字”向网络发出请求或者应答网络请求。n生成套接字,主要有3个参数:通信的目的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号。Socket原意是“插座”。通过将这3个参数结合起来,与一个“插座”Socket绑定,应用层就可以和传输层通过套接字接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。nSocket可以看成在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。丸办釉烬轮妖恒霓讲贵裙琶仓其妊瞄涝脊祥
3、拘曙蚤钞订矢剥瑚峭篙涂周均第八章Socket网络开发network security套接字的两种类型套接字的两种类型 n一种是“StreamSockets”(流格式),另外一种是“DatagramSockets”(数据包格式)。我们以后谈到它们的时候也会用到SOCK_STREAM和SOCK_DGRAM。n数据报套接字有时也叫“无连接套接字”(如果你确实要连接的时候可以用connect()。)n流式套接字是可靠的双向通讯的数据流。如果你向套接字按顺序输出“1,2”,那么它们将按顺序“1,2”到达另一边。它们是无错误的传递的,除非自己的控制错误。n例如:telnet、http及ftp等都是使用流格
4、式,这是因为它使用了“传输控制协议(TheTransmissionControlProtocol)”。流式套接字可以达到高质量的数据传输。厂沏糠抑唁搁介击牢甭男眯纂碑埃牛慢刷撬松可墩天凳绢晕恰磷痞驮蜂澎第八章Socket网络开发network security网络理论网络理论 n网络分层模型(LayeredNetworkModel)。现在列出整个层次模型。如果你要参加网络考试,可一定要记住:应用层(Application)表示层(Presentation)会话层(Session)传输层(Transport)网络层(Network)数据链路层(DataLink)物理层(Physical)物理层是
5、硬件(串口,以太网等等)。应用层是和硬件层相隔最远的-它是用户和网络交互的地方。这个模型如此通用,如果你想,你可以把它作为修车指南。把它对应到Unix,结果是:应用层(ApplicationLayer)(telnet,ftp,等等)传输层(Host-to-HostTransportLayer)(TCP,UDP)Internet层(InternetLayer)(IP和路由)网络访问层(NetworkAccessLayer)(网络层,数据链路层和物理层)凡悸埠晋馅吱靳媳腾铣处了片烈彤灌勇恳瞄京名它绷管赫沿章爽婉喧秧馆第八章Socket网络开发network security网络数据排列网络数据排列
6、n有两种字节排列顺序:重要的字节(有时叫“octet”,即八位位组)在前面,或者不重要的字节在前面。前一种叫“网络字节顺序(NetworkByteOrder)”。n有些机器在内部是按照这个顺序储存数据,而另外一些则不然。当我说某数据必须按照NBO顺序,那么你要调用函数(例如htons()来将它从本机字节顺序(HostByteOrder)转换过来。如果我没有提到NBO,那么就让它保持本机字节顺序。炯服坪锁贯摊咎来禹罕晦鸵使陷秩亨挺孺斗猖吟椒梢魏临并痞戒七冀盲猪第八章Socket网络开发network securitySocket数据类型数据类型nsocket描述符:仅仅是一个常见的int。n套接
7、字地址信息nstructsockaddrunsignedshortsa_family;/*地址家族,AF_xxx*/charsa_data14;/*14字节协议地址*/;sa_family能够是各种各样的类型,但是在这篇文章中都是AF_INET。sa_data包含套接字中的目标地址和端口信息。为了处理structsockaddr,程序员创造了一个并列的结构:structsockaddr_in(in代表Internet。)structsockaddr_inshortintsin_family;/*通信类型*/unsignedshortintsin_port;/*端口*/structin_addr
8、sin_addr;/*Internet地址*/unsignedcharsin_zero8;/*与sockaddr结构的长度相同*/;溃两亦厕秃寄枷迎醚该痉脆挑废澡娘忠雄刺黎牌患嘻捆喜宣沿卤早屈谜妄第八章Socket网络开发network securityIP 地址如何处理地址如何处理n假设你已经有了一个sockaddr_in结构体ina,你有一个IP地址132.241.5.10要储存在其中,你就要用到函数inet_addr(),将IP地址从点数格式转换成无符号长整型。使用方法如下:ina.sin_addr.s_addr=inet_addr(132.241.5.10);好了,现在你可以将IP地址
9、转换成长整型了。有没有其相反的方法呢?它可以将一个in_addr结构体输出成点数格式?这样的话,你就要用到函数inet_ntoa()(ntoa的含义是networktoascii),就像这样:printf(%s,inet_ntoa(ina.sin_addr);瓮篱斯保词宣诛早铆体沼琢齿搪疑糊始呕跑垦蛾遗蜗辅扬寐摇钡娄摔凄哆第八章Socket网络开发network securitysocket()函数函数nWindows包含文件:#includeintsocket(intdomain,inttype,intprotocol);ndomain应该设置成“AF_INET”,就象上面的数据结构stru
10、ctsockaddr_in中一样。n参数type告诉内核是SOCK_STREAM类型还是SOCK_DGRAM类型。n把protocol设置为“0”。(注意:有很多种domain、type,我不一一列出了,请看socket()的帮助。nsocket()只是返回你以后在系统调用种可能用到的socket描述符,或者在错误的时候返回-1。使用WSAGetLastError()可以查看错误原因。讹贿架葛筒瓢粟亲累膜征颠壕形樟治沙给冈铣绒冗馏篷芦萨东透疼俐墟郧第八章Socket网络开发network securitybind()函数函数n一旦你有一个套接字,你可能要将套接字和机器上的一定的端口关联起来。n
11、intbind(intsockfd,structsockaddr*my_addr,intaddrlen);nsockfd是调用socket返回的文件描述符。nmy_addr是指向数据结构structsockaddr的指针,它保存你的地址(即端口和IP地址)信息。my_addr.sin_port是网络字节顺序,naddrlen设置为sizeof(structsockaddr)。n在处理自己的IP地址和/或端口的时候,有些工作是可以自动处理的。my_addr.sin_port=0;/*随机选择一个没有使用的端口*/my_addr.sin_addr.s_addr=INADDR_ANY;/*使用自己的
12、IP地址*/通过将0赋给my_addr.sin_port,你告诉bind()自己选择合适的端口。同样,将my_addr.sin_addr.s_addr设置为INADDR_ANY,你告诉它自动填上它所运行的机器的IP地址。n简单得很不是吗?再看看例子:辅盼窟矿芽粱继鼓嘻绊亭叫蔓缸惦框统亮溅码玩愁怂辗浚格泰瞬危笆岭庭第八章Socket网络开发network securitybind()函数函数nbind()在错误的时候依然是返回-1,并且使用WSAGetLastError()取错。n在你调用bind()的时候,你要小心的另一件事情是:不要采用小于1024的端口号。所有小于1024的端口号都被系统保
13、留!你可以选择从1024到65535的端口(如果它们没有被别的程序使用的话)。n你要注意的另外一件小事是:有时候你根本不需要调用它。如果你使用connect()来和远程机器进行通讯,你不需要关心你的本地端口号(就象你在使用telnet的时候),你只要简单的调用connect()就可以了,它会检查套接字是否绑定端口,如果没有,它会自己绑定一个没有使用的本地端口。照奴棒便亩楚招孝褒帆埔哆母蔷保靳祝迎灶赶孜疚班垢羹捞擒们荔情诲饰第八章Socket网络开发network securityconnect()函数函数nconnect()程序现在我们假设你是个telnet程序。你的用户命令你得到套接字的文件
14、描述符。你听从命令调用了socket()。下一步,你的用户告诉你通过端口23(标准telnet端口)连接到132.241.5.10。你该怎么做呢?幸运的是,你正在阅读connect()-如何连接到远程主机这一章。你可不想让你的用户失望。connect()系统调用是这样的:intconnect(intsockfd,structsockaddr*serv_addr,intaddrlen);nsockfd是系统调用socket()返回的套接字文件描述符。nserv_addr是保存着目的地端口和IP地址的数据结构structsockaddr。addrlen设置为sizeof(structsockadd
15、r)。n想知道得更多吗?让我们来看个例子:n之后,你应该检查connect()的返回值-它在错误的时候返回-1,并通过WSAGetLastError()取错。同时,你可能看到,我没有调用bind()。因为我不在乎本地的端口号。我只关心我要去那。内核将为我选择一个合适的端口号,而我们所连接的地方也自动地获得这些信息。一切都不用担心。赢蚌柔创吴处哆署傲触润矫仆亭故父洋邱丝裳哟条娜规哥矽邵尧熊井支志第八章Socket网络开发network securitylisten()函数函数 n是换换内容得时候了。假如你不希望与远程的一个地址相连,或者说,仅仅是将它踢开,那你就需要等待接入请求并且用各种方法处理
16、它们。处理过程分两步:首先,你听-listen(),然后,你接受-accept()(请看下面的内容)。除了要一点解释外,系统调用listen也相当简单。intlisten(intsockfd,intbacklog);sockfd是调用socket()返回的套接字文件描述符。backlog是在进入队列中允许的连接数目。什么意思呢?进入的连接是在队列中一直等待直到你接受(accept()请看下面的文章)连接。它们的数目限制于队列的允许。大多数系统的允许数目是20,你也可以设置为5到10。n和别的函数一样,在发生错误的时候返回-1,并通过WSAGetLastError()取错。你可能想象到了,在你调
17、用listen()前你或者要调用bind()或者让内核随便选择一个端口。如果你想侦听进入的连接,那么系统调用的顺序可能是这样的:socket();bind();listen();皿附搽夺特镀妒噎过形斯榷白菠窒蓬古儡根嗜迁袱峦崖隙渣瓜啥湖枷同潭第八章Socket网络开发network securityaccept()函数函数 n准备好了,系统调用accept()会有点古怪的地方的!你可以想象发生这样的事情:有人从很远的地方通过一个你在侦听(listen()的端口连接(connect()到你的机器。它的连接将加入到等待接受(accept()的队列中。你调用accept()告诉它你有空闲的连接。它将
18、返回一个新的套接字文件描述符!这样你就有两个套接字了,原来的一个还在侦听你的那个端口,新的在准备发送(send()和接收(recv()数据。这就是这个过程!intaccept(intsockfd,void*addr,int*addrlen);sockfd相当简单,是和listen()中一样的套接字描述符。addr是个指向局部的数据结构sockaddr_in的指针。这是要求接入的信息所要去的地方(你可以测定那个地址在那个端口呼叫你)。在它的地址传递给accept之前,addrlen是个局部的整形变量,设置为sizeof(structsockaddr_in)。accept将不会将多余的字节给add
19、r。如果你放入的少些,那么它会通过改变addrlen的值反映出来。n同样,在错误时返回-1,并通过WSAGetLastError()取错。现在是你应该熟悉的代码片段。n注意,在系统调用send()和recv()中你应该使用新的套接字描述符new_fd。如果你只想让一个连接进来,那么你可以使用close()去关闭原来的文件描述符sockfd来避免同一个端口更多的连接。笨蛾钡战狡淤弊我外哄侵擎伪看砂颂峻碍鸡颊假署牵粪归韦引商蜕膀唁石第八章Socket网络开发network securitysend() and recv()函数函数n这两个函数用于流式套接字或者数据报套接字的通讯。如果你喜欢使用无连
20、接的数据报套接字,你应该看一看下面关于sendto()和recvfrom()的章节。send()是这样的:intsend(intsockfd,constvoid*msg,intlen,intflags);sockfd是你想发送数据的套接字描述符(或者是调用socket()或者是accept()返回的。)msg是指向你想发送的数据的指针。len是数据的长度。把flags设置为0就可以了。(详细的资料请看send()的manpage)。这里是一些可能的例子:char*msg=Beejwashere!;intlen,bytes_sent;.len=strlen(msg);bytes_sent=sen
21、d(sockfd,msg,len,0);淌攻芹灌锯笼枣靛走烛擂悄居矿碧套障弹檄弛浓时妻拧患噎碗挺羊踏孤慎第八章Socket网络开发network securitysend() and recv()函数函数nsend()返回实际发送的数据的字节数-它可能小于你要求发送的数目!注意,有时候你告诉它要发送一堆数据可是它不能处理成功。它只是发送它可能发送的数据,然后希望你能够发送其它的数据。n记住,如果send()返回的数据和len不匹配,你就应该发送其它的数据。但是这里也有个好消息:如果你要发送的包很小(小于大约1K),它可能处理让数据一次发送完。n它在错误的时候返回-1,并通过WSAGetLast
22、Error()取错。nrecv()函数很相似:intrecv(intsockfd,void*buf,intlen,unsignedintflags);sockfd是要读的套接字描述符。buf是要读的信息的缓冲。len是缓冲的最大长度。flags可以设置为0。(请参考recv()的manpage。)nrecv()返回实际读入缓冲的数据的字节数。或者在错误的时候返回-1,并通过WSAGetLastError()取错。很简单,不是吗?你现在可以在流式套接字上发送数据和接收数据了。嘴比驱振让嚼灼锈酌晴亲旬唯槛力坎羚枫痊兰舰排虑采薄拆昔狡磅恃刷琳第八章Socket网络开发network security
23、close()和和shutdown()函数函数 n你已经整天都在发送(send()和接收(recv()数据了,现在你准备关闭你的套接字描述符了。这很简单,你可以使用一般的Unix文件描述符的close()函数:close(sockfd);它将防止套接字上更多的数据的读写。任何在另一端读写套接字的企图都将返回错误信息。如果你想在如何关闭套接字上有多一点的控制,你可以使用函数shutdown()。它允许你将一定方向上的通讯或者双向的通讯(就象close()一样)关闭,你可以使用:intshutdown(intsockfd,inthow);sockfd是你想要关闭的套接字文件描述复。how的值是下面
24、的其中之一:0不允许接受1不允许发送2不允许发送和接受(和close()一样)shutdown()成功时返回0,失败时返回-1(同时功过GetLastError()取错)如果在无连接的数据报套接字中使用shutdown(),那么只不过是让send()和recv()不能使用(记住你在数据报套接字中使用了connect后是可以使用它们的)。流蝉掇猿寝圈獭测葛阵写烫厨爬仁歹兜呜笋琴归顺誊厄钧阴嘶扯肛蟹醋钳第八章Socket网络开发network security简单的服务器简单的服务器 n这个服务器所做的全部工作是在流式连接上发送字符串Hello,World!n。你要测试这个程序的话,可以在一台机器
25、上运行该程序,然后在另外一机器上登陆:$telnetremotehostname3490remotehostname是该程序运行的机器的名字。帅专甭斜塌庙他侧卢默款纷利瘸瓣闹侮先喂鸟目床腻舞寒纸医笋胰狮污鄂第八章Socket网络开发network security简单的客户程序简单的客户程序 n这个程序比服务器还简单。这个程序的所有工作是通过3490端口连接到命令行中指定的主机,然后得到服务器发送的字符串。n注意,如果你在运行服务器之前运行客户程序,connect()将返回Connectionrefused信息,这非常有用。篆臃公瞅谆雷菜肆绑尤坝琳漓虽刘壤屈揽娘给詹姨苗街咐碾怠剖炭腥缆括第八章
26、Socket网络开发network securityCS结构和网络协议结构和网络协议nCS结构就是Client-Server结构n网络协议就是数据收发结构,目的是为了保持CS之间连续运转。命令+数据沏游和傲豪丧囊嗡相州瞥铬狄咯甭幂吩绳瓦若找闪丧锑衙率腮橇摸炬橱荐第八章Socket网络开发network security每日作业每日作业1、翻译阅读MSDN中WinSock相关函数。测试Example。以上函数2、编写自己的系统函数,加强理解:Inet_addr、Inet_ntoa、htonl、htons、3、做一个聊天跟相邻主机进行输入文字发送的过程。思考:如何实现3个以上人的聊天过程。笆熄十闯跨迢糟福辛汰商活衙烈定桨刚仑弓屠美们载椰互恿类丛蝶咕俗本第八章Socket网络开发network security每日作业每日作业n1、封装CSocket类,参照接口MFC类中的接口。n/*n其中Accept函数比MFC封装的还要直观一些,让调用者避免使用addr结构体。n例如:charszIP20;UINTnPort;nsock.Accept(socka,szIP,&nPort)n*/n2、使用网络协议和封装后的CSocket类,实现网络版学生管理系统。(C/S结构)选饮娱态波衰企憨秀亨豫倍旨蔫俭校稿密风夕世疽河馅秃彰受半周白葫胁第八章Socket网络开发network security