《【精品】linux套接字网络编程接口(可编辑.ppt》由会员分享,可在线阅读,更多相关《【精品】linux套接字网络编程接口(可编辑.ppt(251页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Linux套接字网络编程接口中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()第第5章章Linux套接字网络编程接口套接字网络编程接口l网络编程接口的产生与发展网络编程接口的产生与发展l套接字基础套接字基础l面向连接的传输层套接字面向连接的传输层套接字编程编程l无连接的套接字编程无连接的套接字编程l高级套接字函数高级套接字函数l服务器的服务器的I/O模型模型l网络层的原始套接字网络层的原始套接字l面向数据链路层的套接字面向数据链路层的套接字网络编程接口网络编程接口产生与发展产生与发展中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()网络编程接口的产生与发
2、展网络编程接口的产生与发展l问题的提出问题的提出站在应用程序实现的角度,应用程序如何方便地站在应用程序实现的角度,应用程序如何方便地使用协议栈软件进行通信呢?使用协议栈软件进行通信呢?如果能在应用程序与协议栈软件之间提供一个软如果能在应用程序与协议栈软件之间提供一个软件接口,就可以方便客户与服务器软件的编程。件接口,就可以方便客户与服务器软件的编程。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()网络编程接口的产生与发展网络编程接口的产生与发展l套接字编程接口套接字编程接口套接字应用程序编程接口是网络应用程序通过网套接字应用程序编程接口是网络应用程序通过网络协议栈进行通信
3、时所使用的接口,即应用程序络协议栈进行通信时所使用的接口,即应用程序与协议栈软件之间的接口,简称套接字编程接口与协议栈软件之间的接口,简称套接字编程接口(SocketAPI)。它定义了应用程序与协议栈软件进行交互时可以它定义了应用程序与协议栈软件进行交互时可以使用的一组操作,决定了应用程序使用协议栈的使用的一组操作,决定了应用程序使用协议栈的方式、应用程序所能实现的功能、以及开发具有方式、应用程序所能实现的功能、以及开发具有这些功能的程序的难度。这些功能的程序的难度。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华
4、(曾卫华()中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()网络编程接口的产生与发展网络编程接口的产生与发展lLinux系统是通过提供套接字系统是通过提供套接字(socket)来进行来进行网络编程的网络编程的.lSocket技术提供了在技术提供了在TCP/IP模型各个层上的模型各个层上的编程支持。编程支持。l该技术是在内核处理收到的各层协议数据,该技术是在内核处理收到的各层协议数据,然后应用程序以文件的方式接受内核传来的然后应用程序以文件的方式接受内核传来的数据。数据。l应用程序的文件处理是通过一个文件句柄来应用程序的文件处理是通过一个文件句柄来进行的。进行的。中国地质大
5、学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()网络编程接口的产生与发展网络编程接口的产生与发展l网络程序通过网络程序通过socket和其它几个函数的调用和其它几个函数的调用,会返回一个会返回一个 通讯的文件描述符通讯的文件描述符,l我们可以将这个描述符看成普通的文件的描我们可以将这个描述符看成普通的文件的描述符来操作述符来操作,l这就是这就是linux的设备无关性的好处的设备无关性的好处.我们可以通我们可以通过向描述符读写操作实现网络之间的数据交过向描述符读写操作实现网络之间的数据交流流.套接字基础套接字基础中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套
6、接字基础套接字基础l什么是套接字(什么是套接字(SOCKET)l套接口是对网络中不同主机上应用进程之间进行双套接口是对网络中不同主机上应用进程之间进行双向通信的端点的抽象,一个套接口就是网络上进程向通信的端点的抽象,一个套接口就是网络上进程通信的一端,提供了应用层进程利用网络协议栈交通信的一端,提供了应用层进程利用网络协议栈交换数据的机制换数据的机制。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础lSocket Socket 的功能的功能Socket 的英文原意就是的英文原意就是“孔孔”或或“插座插座”,将电话系统与面向连接的,将电话系统与面向连接的
7、Socket 机制相比,有着惊人相似的地方。以一个国家级的电话网为例。机制相比,有着惊人相似的地方。以一个国家级的电话网为例。电话的通话双方相当于相互通信的两个进程;通话双方所在的地区(享电话的通话双方相当于相互通信的两个进程;通话双方所在的地区(享有一个全局唯一的区号)相当于一个网络,区号是它的网络地址;区内有一个全局唯一的区号)相当于一个网络,区号是它的网络地址;区内的一个单位的交换机相当于一台主机,主机分配给每个用户的局内号码的一个单位的交换机相当于一台主机,主机分配给每个用户的局内号码相当于相当于Socket 号号.任何用户在通话之前,首先要占有一部电话机,相当于申请一个任何用户在通话
8、之前,首先要占有一部电话机,相当于申请一个Socket 号;同时要知道对方的电话号码,相当于对方有一个号;同时要知道对方的电话号码,相当于对方有一个Socket。然后向对方拨号呼叫,相当于发出连接请求(假如对方不在同一区内,然后向对方拨号呼叫,相当于发出连接请求(假如对方不在同一区内,还要拨对方区号,相当于给出网络地址)。对方假如在场并空闲(相当还要拨对方区号,相当于给出网络地址)。对方假如在场并空闲(相当于通信的另一主机开机且可以接受连接请求),拿起电话话筒,双方就于通信的另一主机开机且可以接受连接请求),拿起电话话筒,双方就可以正式通话,相当于连接成功。可以正式通话,相当于连接成功。双方通
9、话的过程,是向电话机发出信号和从电话机接受信号的过程,相双方通话的过程,是向电话机发出信号和从电话机接受信号的过程,相当于向当于向Socket 发送数据和从发送数据和从Socket 接受数据。通话结束后,一方挂起电接受数据。通话结束后,一方挂起电话机,相当于关闭话机,相当于关闭Socket,撤消连接。,撤消连接。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础l我们应当从多个层面来理解套接字这个概念的内涵。我们应当从多个层面来理解套接字这个概念的内涵。l从套接字所处的地位来讲,套接字上联应用进程,从套接字所处的地位来讲,套接字上联应用进程,下联网络协议
10、栈,是应用程序通过网络协议栈进行下联网络协议栈,是应用程序通过网络协议栈进行通信的接口,是应用程序与网络协议栈进行交互的通信的接口,是应用程序与网络协议栈进行交互的接口。接口。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础l从实现的角度来讲,非常复杂。从实现的角度来讲,非常复杂。套接字是一个复杂的软件机构,包含了一定的数套接字是一个复杂的软件机构,包含了一定的数据结构,包含许多选项,由操作系统内核管理。据结构,包含许多选项,由操作系统内核管理。l从使用的角度来讲,非常简单。从使用的角度来讲,非常简单。对于套接字的操作形成了一种网络应用程序的编对于套接
11、字的操作形成了一种网络应用程序的编程接口(程接口(API)。)。l本书把这一套操作套接字的编程接口函数称本书把这一套操作套接字的编程接口函数称作套接字编程接口,套接字是它的操作对象。作套接字编程接口,套接字是它的操作对象。l总之,套接字是网络通信的基石。总之,套接字是网络通信的基石。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础l常用的常用的socket:流式套接字:流式套接字:u它提供基于它提供基于TCP协议的双向、可靠、有序且不重复的协议的双向、可靠、有序且不重复的无记录边界的数据流。无记录边界的数据流。数据报套接字:数据报套接字:u它提供基于它
12、提供基于UDP协议的双向数据流,但不一定可靠、协议的双向数据流,但不一定可靠、有序和不重复。有序和不重复。原始套接字:原始套接字:u它提供网络下层通信协议的直接访问。一般用于开发它提供网络下层通信协议的直接访问。一般用于开发新的网络层协议,如新的新的网络层协议,如新的IP协议等。协议等。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字使用的数据类型和相关的问题套接字使用的数据类型和相关的问
13、题l1三种表示套接字地址的结构三种表示套接字地址的结构在套接字编程接口中,专门定义了三种结构型的在套接字编程接口中,专门定义了三种结构型的数据类型,用来存储协议相关的网络地址,在套数据类型,用来存储协议相关的网络地址,在套接字编程接口的函数调用中要用到它们。接字编程接口的函数调用中要用到它们。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础l(1)struct sockaddr这个结构用来存储套接字地址。这个结构用来存储套接字地址。数据定义:数据定义:struct sockaddr unsigned short sa_family;/*address族
14、族,AF_xxx*/char sa_data14;/*14 bytes的协议地址的协议地址*/;sa_family 一般来说,都是一般来说,都是“AF_INET”。sa_data 包含了一些远程电脑的地址、端口和套包含了一些远程电脑的地址、端口和套接字的数目,它里面的数据是杂溶在一切的。接字的数目,它里面的数据是杂溶在一切的。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础l(2).(2).struct sockaddr_in为了处理为了处理struct sockaddr,程序员建立了另外一个相似程序员建立了另外一个相似的结构的结构struct soc
15、kaddr_in:struct sockaddr_in(“in”代表代表“Internet”)struct sockaddr_in short int sin_family;/*Internet地址族地址族*/unsigned short int sin_port;/*端口号端口号*/struct in_addr sin_addr;/*Internet地址地址*/unsigned char sin_zero8;/*添添0(和(和struct sockaddr一一样大小)样大小)*/;这个结构提供了方便的手段来访问这个结构提供了方便的手段来访问socket address(struct sock
16、addr)结构中的每一个元素。)结构中的每一个元素。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础l(3)struct in_addr专门用来存储专门用来存储IP地址,其定义如下:地址,其定义如下:/*因特网地址因特网地址(a structure for historical reasons)*/struct in_addr unsigned long s_addr;如果你声明了一个如果你声明了一个“ina”作为一个作为一个struct sockaddr_in 的结构,的结构,那么那么“ina.sin_addr.s_addr”就是就是4 个字节的个字
17、节的IP 地址(按网地址(按网络字节顺序排放)。络字节顺序排放)。需要注意的是,即使你的系统仍然使用联合而不是结构来表示需要注意的是,即使你的系统仍然使用联合而不是结构来表示struct in_addr,你仍然可以用上面的方法得到,你仍然可以用上面的方法得到4 个字节的个字节的IP 地址地址.中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字基础套接字基础l(4).这些数据结构的一般用法:这些数据结构的一般用法:首先,定义一个首先,定义一个Sockaddr_in的结构实例,并将的结构实例,并将它清零。比如:它清零。比如:structsockaddr_inmyad;me
18、mset(&myad,0,sizeof(structsockaddr_in);然后,为这个结构赋值,比如:然后,为这个结构赋值,比如:myad.sin_family=AF_INET;myad.sin_port=htons(8080);myad.sin_addr.s_addr=htonl(INADDR-ANY);第三步:在函数调用中使用时,将这个结构强制第三步:在函数调用中使用时,将这个结构强制转换为转换为sockaddr类型。如:类型。如:accept(listenfd,(sockaddr*)(&myad),&addrlen);中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华
19、()套接字使用的数据类型和相关的问题套接字使用的数据类型和相关的问题l2本机字节顺序和网络字节顺序本机字节顺序和网络字节顺序在具体计算机中的多字节数据的存储顺序,称为本机字节在具体计算机中的多字节数据的存储顺序,称为本机字节顺序。多字节数据在网络协议报头中的存储顺序,称为网顺序。多字节数据在网络协议报头中的存储顺序,称为网络字节顺序。络字节顺序。u在网络上面有着许多类型的机器在网络上面有着许多类型的机器,这些机器在表示数据这些机器在表示数据的字节顺序是不同的的字节顺序是不同的,比如比如i386芯片是低字节在内存地芯片是低字节在内存地址的低端址的低端,高字节在高端高字节在高端,而而alpha芯片
20、却相反芯片却相反.为了统一起来为了统一起来,在在Linux下面下面,有专门的字节转换函数有专门的字节转换函数.unsigned long int htonl(unsigned long int hostlong)unsigned long int htonl(unsigned long int hostlong)unsigned short int htons(unisgned short int hostshort)unsigned short int htons(unisgned short int hostshort)unsigned long int ntohl(unsigned lo
21、ng int netlong)unsigned long int ntohl(unsigned long int netlong)unsigned short int ntohs(unsigned short int netshort)unsigned short int ntohs(unsigned short int netshort)在这四个转换函数中在这四个转换函数中,h 代表代表host,n 代表代表 network.s 代表代表short l 代表代表long 第一个函数的意义是将本机器上的第一个函数的意义是将本机器上的long数数据转化为网络上的据转化为网络上的long.其他几个
22、函数的意义也差不多其他几个函数的意义也差不多.中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字使用的数据类型和相关的问题套接字使用的数据类型和相关的问题l3点分十进制的点分十进制的IP地址的转换地址的转换(1)inet_atonu将将strptr所指的字符串转换成所指的字符串转换成32位的网络字节序二进制位的网络字节序二进制值。值。include int inet_aton(const char*strptr,struct in_addr*addrptr);(2)inet_addru功能同上,返回地址。功能同上,返回地址。int_addr_t inet_addr(c
23、onst char*strptr);(3)inet_ntoau将将32位网络字节序二进制地址转换成点分十进制的串。位网络字节序二进制地址转换成点分十进制的串。char*inet_ntoa(stuct in_addr inaddr);中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字使用的数据类型和相关的问题套接字使用的数据类型和相关的问题l4域名服务域名服务在网络上标志一台机器可以用在网络上标志一台机器可以用IP或者是用域名或者是用域名.那么我们怎么去进行那么我们怎么去进行转换呢转换呢?ustructhostent*gethostbyname(constchar*ho
24、stname)可以将机器名可以将机器名(如如)转换为一个结构指针转换为一个结构指针.在这个结构里面在这个结构里面储存了域名的信息储存了域名的信息ustructhostent*gethostbyaddr(constchar*addr,intlen,inttype)可以将一个可以将一个32位的位的IP地址地址(C0A80001)转换为结构指针转换为结构指针.这两个函数失败时返回这两个函数失败时返回NULL且设置且设置h_errno错误变量错误变量,调用调用h_strerror()可可以得到详细的出错信息以得到详细的出错信息structhostent的定义的定义:structhostentchar*
25、h_name;/*主机的正式名称主机的正式名称*/char*h_aliases;/*主机的别名主机的别名*/inth_addrtype;/*主机的地址类型主机的地址类型AF_INET*/inth_length;/*主机的地址长度主机的地址长度对于对于IP4是是4字节字节32位位*/char*h_addr_list;/*主机的主机的IP地址列表地址列表*/#defineh_addrh_addr_list0/*主机的第一个主机的第一个IP地址地址*/面向连接的传输层套接字面向连接的传输层套接字编程编程中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()面向连接的传输层套接字面向连
26、接的传输层套接字编程编程l套接字的工作过程套接字的工作过程l初等网络函数初等网络函数l完整的读写函数完整的读写函数l面向连接的传输层套接字面向连接的传输层套接字举例举例l进程控制进程控制中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()套接字的工作过程套接字的工作过程中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l1 socket#include int socket(int domain,int type,int protocol)socket为网络通讯做基本的准备为网络通讯做基本的准备.成功时返回文件成功时返回文件描述符描
27、述符,失败时返回失败时返回-1。通过通过errno可知道出错的详细情况可知道出错的详细情况.中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l参数说明:参数说明:domain:说明我们网络程序所在的主机采用的通讯说明我们网络程序所在的主机采用的通讯协族协族(AF_UNIX和和AF_INET等等)。uAF_UNIX只能够用于单一的只能够用于单一的Unix系统进程间通信系统进程间通信,而而AF_INET是针对是针对Internet的的,因而可以允许在远程主机因而可以允许在远程主机之间通信之间通信u当我们当我们 man socket时发现时发现 doma
28、in可选项是可选项是 PF_*而不而不是是AF_*,因为因为glibc是是posix的实现的实现 所以用所以用PF代替了代替了AF,不过我们都可以使用的不过我们都可以使用的.中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数type:我们网络程序所采用的通讯协议。我们网络程序所采用的通讯协议。uSOCK_STREAM表明我们用的是表明我们用的是TCP协议协议,这样会提供这样会提供按顺序的按顺序的,可靠可靠,双向双向,面向连接的比特流面向连接的比特流.u SOCK_DGRAM 表明我们用的是表明我们用的是UDP协议协议,这样只会提这样只会提供定长的供定
29、长的,不可靠不可靠,无连接的通信。无连接的通信。uSOCK_RAW 原始套接字,用来直接访问原始套接字,用来直接访问IP协议。协议。protocol:由于我们指定了由于我们指定了type,所以这个地方我们一所以这个地方我们一般只要用般只要用0来代替就可以了。来代替就可以了。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l2 bind int bind(int sockfd,struct sockaddr*my_addr,int addrlen)bind将本地的端口同将本地的端口同socket返回的文件描述符捆返回的文件描述符捆绑在一起绑在一起.成
30、功是返回成功是返回0,失败的情况和失败的情况和socket一样。一样。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l参数说明参数说明sockfd:是由是由socket调用返回的文件描述符调用返回的文件描述符.addrlen:是是sockaddr结构的长度结构的长度.my_addr:是一个指向是一个指向sockaddr的指针的指针.中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l构造套接字地址举例:构造套接字地址举例:int listenfd;struct sockaddr_in server_ad
31、dr;listenfd=socket(AF_INET,SOCK_STREAM,0);bzero(&server_addr,sizeof(server_addr);server_addr.sin_family=AF_INET;server_addr.sin_port=htons(80);inet_pton(AF_INET,“211.83.241.244”,&server_addr.sin_addr);bind(listenfd,&server_addr,sizeof(struct sockaddr_in)中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函
32、数l3 listen int listen(int sockfd,int backlog)listen函数将函数将bind的文件描述符变为监听套接字。的文件描述符变为监听套接字。返回的情况和返回的情况和bind一样。一样。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l参数说明参数说明sockfd:是是bind后的文件描述符后的文件描述符.。backlog:设置请求排队的最大长度设置请求排队的最大长度.当有多个客户当有多个客户端程序和服务端相连时端程序和服务端相连时,使用这个表示可以介绍的使用这个表示可以介绍的排队长度。排队长度。中国地质大学中国
33、地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l4 accept int accept(int sockfd,struct sockaddr*addr,int*addrlen)accept成功时返回最后的服务器端的文件描述符,成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了。这个时候服务器端可以向该描述符写信息了。失败时返回失败时返回-1。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l参数说明参数说明sockfd:是是listen后的文件描述符后的文件描述符.。addr,addrlen
34、是用来给客户端的程序填写的,服务是用来给客户端的程序填写的,服务器端只要传递指针就可以了器端只要传递指针就可以了.。bind,listen和和accept是服务器端用的函数是服务器端用的函数,accept调调用时,服务器端的程序会一直阻塞到有一个用时,服务器端的程序会一直阻塞到有一个 客户客户程序发出了连接,程序发出了连接,accept成功时返回最后的服务成功时返回最后的服务器端的文件描述符。器端的文件描述符。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l5 connect int connect(int sockfd,struct socka
35、ddr*serv_addr,int addrlen)connect函数是客户端用来同服务端连接的。函数是客户端用来同服务端连接的。成功时返回成功时返回0,sockfd是同服务端通讯的文件描述是同服务端通讯的文件描述符符。失败时返回失败时返回-1。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()初等网络函数初等网络函数l参数说明参数说明sockfd:socket返回的文件描述符返回的文件描述符.serv_addr:储存了服务器端的连接信息储存了服务器端的连接信息.其中其中sin_add是服务端的地址是服务端的地址 addrlen:serv_addr的长度的长度 中国地质大学
36、中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()面向连接的传输层套接字面向连接的传输层套接字l课后作业课后作业编写简单的扫描器编写简单的扫描器u端口扫描可以扫描一定范围内的端口;端口扫描可以扫描一定范围内的端口;uIP扫描可以扫描一定范围内的主机。扫描可以扫描一定范围内的主机。u提示:提示:向一个套接字发起连接,成功则可以将其输出。向一个套接字发起连接,成功则可以将其输出。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()完整的读写函数完整的读写函数l一旦我们建立了连接一旦我们建立了连接,我们的下一步就是进行我们的下一步就是进行通信了通信了.l在在Linux下面把
37、我们前面建立的通道下面把我们前面建立的通道 看成是文看成是文件描述符件描述符,这样服务器端和客户端进行通信时这样服务器端和客户端进行通信时候候,只要往文件描述符里面读写东西了只要往文件描述符里面读写东西了.就象我就象我们往文件读写一样。们往文件读写一样。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()完整的读写函数完整的读写函数l1 写函数write ssize_t write(int fd,const void*buf,size_t nbytes)ssize_t write(int fd,const void*buf,size_t nbytes)write函数将函数将b
38、uf中的中的nbytes字节内容写入文件描字节内容写入文件描述符述符fd.成功时返回写的字节数成功时返回写的字节数.失败时返回失败时返回-1.并设置并设置errno变量变量.中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()完整的读写函数完整的读写函数在网络程序中在网络程序中,当我们向套接字文件描述符写时有当我们向套接字文件描述符写时有俩种可能俩种可能.1)write的返回值大于的返回值大于0,表示写了部分或者是全部表示写了部分或者是全部的数据的数据.2)返回的值小于返回的值小于0,此时出现了错误此时出现了错误.我们要根据错我们要根据错误类型来处理误类型来处理.如果错误为如
39、果错误为EINTR表示在写的时候出现了中断错表示在写的时候出现了中断错误误.如果为如果为EPIPE表示网络连接出现了问题表示网络连接出现了问题(对方已经对方已经关闭了连接关闭了连接).中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()完整的读写函数完整的读写函数l为了处理以上的情况为了处理以上的情况,我们自己编写一个写函数来处理这几种情况我们自己编写一个写函数来处理这几种情况.int my_write(int fd,void*buffer,int length)int my_write(int fd,void*buffer,int length)int bytes_left
40、;int bytes_left;int written_bytes;int written_bytes;char*ptr;char*ptr;ptr=buffer;ptr=buffer;bytes_left=length;bytes_left=length;while(bytes_left0)while(bytes_left0)/*/*开始写开始写*/written_bytes=write(fd,ptr,bytes_left);written_bytes=write(fd,ptr,bytes_left);if(written_bytes=0)/*if(written_bytes0)while(b
41、ytes_left0)bytes_read=read(fd,ptr,bytes_read);bytes_read=read(fd,ptr,bytes_read);if(bytes_read0)if(bytes_read0)if(errno=EINTR)if(errno=EINTR)bytes_read=0;bytes_read=0;else else return(-1);return(-1);else else if(bytes_read=0)break;if(bytes_read=0)break;bytes_left-=bytes_read;bytes_left-=bytes_read;p
42、tr+=bytes_read;ptr+=bytes_read;return(length-bytes_left);return(length-bytes_left);中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()完整的读写函数完整的读写函数l3 数据的传递 有了上面的两个函数有了上面的两个函数,我们就可以向客户端或者是我们就可以向客户端或者是服务端传递数据了服务端传递数据了.比如我们要传递一个结构比如我们要传递一个结构.可以可以使用如下方式使用如下方式:/*/*客户端向服务端写客户端向服务端写*/struct my_struct my_struct_client;str
43、uct my_struct my_struct_client;write(fd,(void*)&my_struct_client,sizeof(struct write(fd,(void*)&my_struct_client,sizeof(struct my_struct);my_struct);中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()完整的读写函数完整的读写函数/*/*服务端的读服务端的读*/char buffersizeof(struct my_struct);char buffersizeof(struct my_struct);struct*my_stru
44、ct_server;struct*my_struct_server;read(fd,(void*)buffer,sizeof(struct my_struct);read(fd,(void*)buffer,sizeof(struct my_struct);my_struct_server=(struct my_struct*)buffer;my_struct_server=(struct my_struct*)buffer;在网络上传递数据时我们一般都是把数据转化为在网络上传递数据时我们一般都是把数据转化为char类型的数据传递类型的数据传递.接收的时候也是一样的。接收的时候也是一样的。注意的
45、是我们没有必要在网络上传递指针注意的是我们没有必要在网络上传递指针(因为传因为传递指针是没有任何意义的递指针是没有任何意义的,我们必须传递指针所指我们必须传递指针所指向的内容向的内容)。中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()面向连接的传输层套接字面向连接的传输层套接字举例举例l服务器端程序/*/*服务器程序服务器程序 (server.c)*/(server.c)*/#include#include#include#include#include#include#include#include#include#include#include#include#inc
46、lude#include#include#include 中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()面向连接的传输层套接字面向连接的传输层套接字举例举例 int main(int argc,char*argv)int main(int argc,char*argv)int sockfd,new_fd;int sockfd,new_fd;struct sockaddr_in server_addr;struct sockaddr_in server_addr;struct sockaddr_in client_addr;struct sockaddr_in clien
47、t_addr;int sin_size,portnumber;int sin_size,portnumber;char hello=Hello!Are You Fine?n;char hello=Hello!Are You Fine?n;if(argc!=2)if(argc!=2)fprintf(stderr,Usage:%s portnumberan,argv0);fprintf(stderr,Usage:%s portnumberan,argv0);exit(1);exit(1);if(portnumber=atoi(argv1)0)if(portnumber=atoi(argv1)0)f
48、printf(stderr,Usage:%s portnumberan,argv0);fprintf(stderr,Usage:%s portnumberan,argv0);exit(1);exit(1);中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()面向连接的传输层套接字面向连接的传输层套接字举例举例/*/*服务器端开始建立服务器端开始建立socketsocket描述符描述符*/if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1)if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1)fprintf(st
49、derr,Socket error:%sna,strerror(errno);fprintf(stderr,Socket error:%sna,strerror(errno);exit(1);exit(1);/*/*服务器端填充服务器端填充 sockaddrsockaddr结构结构*/bzero(&server_addr,sizeof(struct sockaddr_in);bzero(&server_addr,sizeof(struct sockaddr_in);server_addr.sin_family=AF_INET;server_addr.sin_family=AF_INET;ser
50、ver_addr.sin_addr.s_addr=htonl(INADDR_ANY);server_addr.sin_addr.s_addr=htonl(INADDR_ANY);server_addr.sin_port=htons(portnumber);server_addr.sin_port=htons(portnumber);中国地质大学中国地质大学(北京北京)地信学院地信学院曾卫华(曾卫华()面向连接的传输层套接字面向连接的传输层套接字举例举例/*/*捆绑捆绑sockfdsockfd描述符描述符*/if(bind(sockfd,(struct sockaddr if(bind(sock