全套课件·《Linux/UNIX网络编程》1.ppt

上传人(卖家):三亚风情 文档编号:3158628 上传时间:2022-07-25 格式:PPT 页数:380 大小:3.33MB
下载 相关 举报
全套课件·《Linux/UNIX网络编程》1.ppt_第1页
第1页 / 共380页
全套课件·《Linux/UNIX网络编程》1.ppt_第2页
第2页 / 共380页
全套课件·《Linux/UNIX网络编程》1.ppt_第3页
第3页 / 共380页
全套课件·《Linux/UNIX网络编程》1.ppt_第4页
第4页 / 共380页
全套课件·《Linux/UNIX网络编程》1.ppt_第5页
第5页 / 共380页
点击查看更多>>
资源描述

1、Linux/UNIX网络编程先修课程C语言TCP/IP协议操作系统原理Linux的基本使用Linux系统基础系统基础软件开发环境最常用编辑工具:vi编译器:gcc,g+gcc编译c程序 g+编译c+程序调试器:gdb基本的C/S服务模型 n简单的客户/服务器模型1、数据请求2、数据响应无连接3、数据请求4、数据响应1、连接请求2、连接响应5、关闭请求6、关闭响应复杂的客户/服务器模型WEB服务器和客户端之间的数据传输过程 OSI 与 TCP/IP应用层表示层会话层传输层网络层数据链路层物理层应用层IPv4,IPv6网络介质层TCPUDPOSI模型TCP/IP模型网络编程接口通过路由器连接的两个

2、网络FTP客户TCPIP以太网驱动程序FTP服务器TCPIP令牌环驱动程序令牌环以太网驱动程序令牌环驱动程序IPFTP协议TCP协议IP协议IP协议以太网客户服务器数据进入协议栈时的封装用户数据用户数据App头部用户数据TCP头部用户数据TCP头部IP头部用户数据TCP头部IP头部以太网头部以太网尾部以太网帧401500字节FTP客户TCPIP以太网驱动程序TCP段IP分组以太网数据帧分用过程以太网帧ARPRARPIPICMPIGMPTCPUDP应用程序应用程序应用程序应用程序进入的帧根据以太网首部中的帧类型进行分用根据IP首部中的协议类型进行分用根据TCP或UDP首部中的端口号进行分用UDP

3、:用户数据报协议 UDP提供无连接服务 UDP缺乏可靠性支持,应用程序必须实现:确认、超时、重传、流控等 UDP面向记录服务UDP数据报格式源端口目的端口长度校验和数据01531#ifdef _FAVOR_BSDstruct udphdr u_int16_t uh_sport;/*source port*/u_int16_t uh_dport;/*destination port*/u_int16_t uh_ulen;/*udp length*/u_int16_t uh_sum;/*udp checksum*/;#elsestruct udphdr u_int16_t source;u_int

4、16_t dest;u_int16_t len;u_int16_t check;#endifTCP:传输控制协议 TCP是面向连接的。TCP提供可靠性,实现了丢失重传。RTT的估算。TCP通过给所发送数据的每一个段管理一个序列号进行排序。TCP提供流量控制和拥塞控制:通告窗口、拥塞窗口。TCP的连接是全双工的。TCP协议数据段格式HLEN窗口序列号确认号源端口目的端口保留码位校验和紧急指针选项填充字节数据URGACKPSHRSTSYNFIN015317首部数据区TCP协议数据段格式(续)struct tcphdr WORD SourPort;WORD DestPort;DWORD SeqNo;

5、DWORD AckNo;BYTE HLen;BYTE Flag;WORD Window;WORD ChkSum;WORD UrgPtr;/*Put options here.*/;TCP协议数据段格式(续)TCP协议数据段格式(续)TCP协议数据段格式(续)TCP三路握手客户服务器SocketConnect(阻塞)(主动打开)Socket,bind,listen(被动打开)SYN xSYN y,ack x+1ack y+1Accept返回Read阻塞Connect返回TCP连接的建立 TCP连接的过程:服务器必须准备好接受外来的连接。通过调用socket,bind,listen函数完成。称为被

6、动打开。客户通过调用connect进行主动打开。这引起客户TCP发送一个SYN分节,告诉服务器客户将在连接中发送的数据的初始序列号。服务器必须确认客户的SYN,同时自己也得发送一个SYN分节。服务器以单个分节向客户发送SYN和对客户的SYN的ACK。客户必须确认服务器的SYN。TCP连接关闭客户服务器Close主动关闭被动关闭Read返回0FIN Mack N+1Closeack M+1FIN NTCP连接终止 TCP一般用四个分节终止一个连接:某个进程首先调用close,这一端的TCP于是发送一个FIN分节,表示数据发送完毕。主动关闭。另一端称为被动关闭。TCP对接收的FIN分节进行确认,并

7、以文件结束标志传递给应用程序。一段时间后,接收到文件结束标志的应用程序调用close,这也导致向对方发送一个FIN分节。接收到这个FIN分节的原发送方TCP对它进行确认。还有一种关闭称为“半关闭”(half-close)CLOSELISTENSYN_RCVDSYN_SENTESTABLISHEDCLOSE_WAITLAST_ACKFIN_WAIT1FIN_WAIT2TIME_WAITCLOSING被动关闭主动关闭应用:close或超时接收:ACK发送:应用:close发送:FIN应用:主动打开发送:SYN起始点应用:被动打开发送:接收:SYN;发送:SYN,ACK接收:RST接收:SYN发送:

8、SYN,ACK,同时打开接收:ACK发送:应用:close发送FIN同时关闭接收:ACK发送:接收:FIN,ACK发送:ACK接收:FIN发送:ACK,接收:ACK发送:2MSL超时?接收:SYN,ACK发送:ACK接收:FIN发送:ACK接收:FIN发送:ACK,表示客户的状态转换表示服务器的状态转换socket,bind,listenLISTEN(被动打开)accept阻塞SocketConnect(阻塞)(主动打开)SYN_SENTSYN_RCVDESTABLISHEDESTABLISHEDaccept返回read阻塞read返回客户构造请求WriteRead(阻塞)WriteRead阻

9、塞Read(返回)CLOSE_WAIT(被动关闭)Read返回0CloseLAST_ACKClose(主动关闭)FIN_WAIT1FIN_WAIT2TIME_WAITCLOSED2MSLSYN J,mss=1460SYN K,ACK J+1,mss=1024ACK k+1数据(请求)数据(应答),请求ack应答ackFIN MACK M+1FIN NACK N+1TCP连接中的分组交换TCP 的TIME_WAIT状态 难点:执行主动关闭的那端进入这种状态。这个端点在该状态的持续时间是2MSL(最长分节生命周期)。存在TIME_WAIT状态的两个理由?物理地址:即MAC地址 逻辑地址:即IP地址

10、 端口地址:应用程序端口号 域名地址:取代IP地址记忆物理地址 48位:24位OUI,24位由厂商分配 平面地址,无结构 全球唯一 局部范围寻址 存在于数据链路层IP地址 IP地址标识着网络一个主机的位置。每个IP地址都是由32位(或128位)组成,分成两部分:网络号、主机号。全球唯一,寻址容易 两种表示形式:二进制(计算机内部)、点分十进制(便于记忆)IP地址分类0 NetID10110NetID1110Multicast AddressHostIDNetIDHostIDHostID8 bits8 bits8 bits8 bits0126128191192223224239基本套接字编程主要

11、内容主要内容 套接字基础 套接字地址结构 套接字基本函数 套接字基础套接字基础 网络编程接口有两个发展方向:Socket,TLI 套接字是一种网络API,程序员可以用之开发网络程序。进程1进程2网络编程接口(socket)网络通信协议服务接口(TCP/IP)底层通信协议和网络介质套接字类型套接字类型 套接字支持多种通信协议:Unix:Unix系统内部协议 INET:IP版本4 INET6:IP版本6 Linux支持多种套接字类型,即应用程序希望的通信服务类型 SOCKET_STREAM:双向可靠数据流,对应TCP SOCKET_DGRAM:双向不可靠数据报,对应UDP SOCKET_RAW:是

12、低于传输层的低级协议或物理网络提供的套接字类型,可以访问内部网络接口。例如接收和发送ICMP报套接字地址结构(IPv4)大多数套接字函数需要一个指向套接字地址结构的参数,每个协议族都定义它自己的套接字地址结构,一般以”sockaddr_”开头,并以协议簇为后缀。(netinet/in.h)typedef uint32_t in_addr_t;typedef uint16_t in_port_t;typedef unsigned short sa_family_t;struct in_addr in_addr_t s_addr;struct sockaddr_in uint8_t sin_len

13、;sa_family_t sin_family;in_port_t sin_port;struct in_addr sin_addr;char sin_zero8;struct sockaddr_in serverbzero(&server,sizeof(server)server.sin_family=AF_INET;server.sin_port=htons(PORT);server.sin_addr.s_addr=htonl(INADDR_ANY).IPv6地址为128位。(netinet/in.h)套接字地址结构(IPv6)typedef uint16_t in_port_t;type

14、def unsigned short sa_family_t;struct in6_addr uint8_ts6_addr16;struct sockaddr_in6 uint8_t sin6_len;sa_family_t sin6_family;in_port_t sin6_port;uint32_t sin6_flowinfo;struct in6_addr sin6_addr;sin6_flowinfo成员分成三个字段:n低24位是流量标号;n下4位是优先级;n再下4位保留IPv4与IPv6地址结构比较长度AF_INET616位端口号32位流标签128位IPv6地址sockaddr_i

15、n6 长度AF_INET16位端口号32位IP地址未用sockaddr_in 固定长度(16字节)固定长度(24字节)通用套接字地址结构通用套接字地址结构 由于套接字函数需接收来自不同协议的地址结构,ANSI的办法是使用通用的指针类型,即(void*).套接字函数方法是定义一个通用的套接字地址结构。struct sockaddr uint8_t sa_len;sa_family_t sa_family;char sa_data14;这就要求调用套接字函数时,需将指向特定于协议的地址结构的指针类型转换成指向通用的地址结构的指针,如:struct sockaddr_in serv bind(soc

16、kfd,(struct sockaddr*)&serv,sizeof(serv);字节排序函数 为保证”大端“和”小端“字节序的机器之间能相互通信,需在发送多字节整数时,将主机字节序转换成网络字节序,或反之。高序字节低序字节MSB(最高有效位)16位值 LSB高序字节低序字节内存地址增大方向内存地址增大方向小端字节序大端字节序网络字节序字节排序函数(cont.)#include uint16_t htons(uint16_t hostshort)uint32_t htonl(uint32_t hostlong)均返回:网络字节序值uint16_t ntohs(uint16_t netshort

17、)uint32_t ntohl(uint32_t netlong)均返回:主机字节序值h:主机 n:网络 s:短整数 l:长整数字节操纵函数#include void bzero(void*dest,size_t nbytes);void bcopy(const void*src,void*dest,size_t nbytes);int bcmp(const void*src,void*dest,size_t nbytes);/*返回0则相同,非0不相同*/上述三个函数源自BSDvoid*memset(void*dest,int c,size_t len);void*memcpy(void*d

18、est,const void*src,size_t nbytes);int memcmp(const void*ptr1,const void*ptr2,size_t nbytes)上述三个函数属于ANSI C地址转换函数#include 将点分十进制数串转换成32位网络字节序二进制值。int inet_aton(const char*cp,struct in_addr*inp);返回:1-串有效,0-串有错in_addr_t inet_addr(const char*cp);返回:若成功,返回32位二进制的网络字节序地址,若有错,则返回一个 常值INADDR_NONE(32位均为1).ine

19、t_aton函数将cp所指的字符串(点分十进制数串,如192.168.0.1)转换成32位的网络字节序二进制,并通过指针inp来存储。这个函数需要对字符串所指的地址进行有效性验证。但如果cp为空,函数仍然成功,但不存储任何结果。inet_addr进行相同的转换,但不进行有效性验证,也就是说,所有232种可能的二进制值对inet_addr函数都是有效的。地址转换函数(续)地址转换函数(续)char*inet_ntoa(struct in_addr inaddr);返回:指向点分十进制数串的指针 函数inet_ntoa将32位的网络字节序二进制IPv4地址转换成相应的点分十进制数串。但由于返回值所

20、指向的串留在静态内存中,这意味着函数是不可重入的。需要注意的是这个函数是以结构为参数的,而不是指针。上述三个地址转换函数都只能处理IPv4协议,而不能处理IPv6地址。地址转换函数(地址转换函数(cont.)#include int inet_pton(int family,const char*strptr,void*addrptr);返回:1-成功,0输入无效,-1:出错const char*inet_ntop(int family,const void*addrptr,char*strptr,size_t len);返回:指向结果的指针成功,NULL出错字母P和N分别代表presenta

21、tion(地址的表达格式)和numeric(数值格式)。family参数可以是AF_INET,也可以是AF_INET6。长度参数len是目标的大小,如果太小无法容纳表达格式结果,则返回一个空指针。另外,目标指针调用前必须先由调用者分配空间。表达式格式数值格式inet_pton(AF_INET)inet_aton,inet_addr适用IPv4地址inet_ntop(AF_INET)inet_ntoainet_pton(AF_INET4/6)即可用于IPv4地址,又可用于IPv6地址inet_ntop(AF_INET4/6)适用IPv6地址inet_pton(AF_INET6)inet_ntop

22、(AF_INET6)表达式格式表达式格式数值格式数值格式Tcp套接字编程TCP套接字编程(cont.)基本套接字函数socket#include int socket(int family,int type,int protocol)返回:非负套接字(sockfd)成功;-1出错。family:协议族;type:套接字类型;protocol:一般为0,除原始套接字外。family typeAF_INET IPv4协议SOCK_STREAM 字节流套接口AF_INET6IPv6协议SOCK_DGRAM 数据报套接口AF_LOCALunix域协议SOCK_RAW 原始套接口AF_ROUTE 路由套

23、接口AF_KEY 密钥套接口Protocol:指明此socket请求所使用的协议,可以使用如下相关符号常数来表示。IPPROTO_TCP:表示TCP协议IPPROTO_UDP:表示UDP协议 AF_INET AF_INET6 AF_LOCAL AF_ROUTE AF_KEY SOCK_STREAM TCP TCP Yes SOCK_DGRAM UDP UDP Yes SOCK_RA W IPv4 IPv6 Yes Yes 基本套接字函数bind#include int bind(int sockfd,const struct sockaddr*addr,socklen_len len)返回:0

24、成功;-1出错并置errno 该函数指明套接字将使用本地的哪一个协议端口进行数据传送(IP地址和端口号),注意:协议地址addr是通用地址。Len是该地址结构(第二个参数)的长度。一般而言,服务器调用此函数,而客户则很少调用它。绑定地址时,可以指定地址和端口号,也可以指定其中之一,甚至一个也不指定。通配地址:INADDR_ANY,其值一般为0,它通知内核选择IP地址。IP地址 端口 结果通配地址 0 内核选择IP地址和端口号通配地址 非0 内核选择IP地址,进程指定端口本地IP 0 进程指定IP地址,内核选择端口本地IP 非0 进程指定IP地址和端口号 若指定端口号为0,调用函数bind时,内

25、核选择一个临时端口(在实际中,端口号都要指定);但若指定一个通配IP地址,则直到套接字已连接(TCP)或数据报已在套接字上发出(UDP),内核才选择一个本地IP地址。bind函数的用法struct sockaddr_in addr;int port=1234;int opt=SO_REUSEADDR;setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt);bzero(&server,sizeof(server);addr.sin_family=AF_INET;addr.sin_addr.s_addr=htonl(INADDR_ANY);ad

26、dr.sin_port=htons(port);if(bind(fd,(struct sockaddr*)&addr,sizeof(addr)=-1)/*错误处理*/基本套接字函数listen#include int listen(int sockfd,int backlog)返回:0成功;-1出错并置errno值;函数listen仅被服务器调用,它完成两件事情:函数listen将未连接的套接字转化成被动套接字,指示内核应接受指向此套接字的连接请求;函数的第二个参数规定了内核为此套接字排队的最大连接个数;对于给定的监听套接字,内核要维护两个队列 未完成连接队列 已完成连接队列 两个队列之和不超

27、过backlog;客户服务器Connect调用在未完成队列建立条目SYN JSYN K,ack J+1ack K+1该条目从未完成队列移至已完成队列,accept阻塞Connect返回TCP三路握手和监听套接口的两个队列listen函数(续)三路握手完成两队列之和不能超过backlog已完成连接队列(ESTABLISHED状态)未完成连接队列(SYN_RCVD状态)新到达的SYN分节服务器TCPacceptlisten函数(续)另外几点说明:不同的实现对backlog有不同的解释,如源自Berkeley的实现将backlog增加一个模糊因子,把它乘以1.5,再作为两个队列之和;不要把backl

28、og定义为0,因为有些实现允许1个连接排队,而有些实现不允许有连接排队;当一个客户SYN到达时,若两个队列都是满的,tcp就忽略此分节,且不发送RST。这是因为,这种情况是暂时的,客户tcp将重发SYN,期望不久的将来就能在队列中找到空闲条目。基本套接字函数connect#include int connect(int sockfd,const struct sockaddr*addr,socklen_t addrlen);返回:0成功;-1出错;函数connect激发TCP的三路握手过程;仅在成功或出错返回;错误有以下几种情况:如果客户没有收到SYN分节的响应(总共75秒,这之间需要可能需要

29、重发若干次SYN),则返回ETIMEDOUT。如果对客户的SYN的响应是RST,则表明该服务器主机在指定的端口上没有进程在等待与之相连。函数返回错误ECONNREFUSED;如果客户发出的SYN在中间路由器上引发一个目的地不可达ICMP错误,客户上的内核保存此消息,并按第一种情况,连续发送SYN,直到规定时间,返回保存的消息(即ICMP错误)作为EHOSTUNREACH或ENETUNREACH错误返回给进程。基本套接字函数accept#include int accept(int sockfd,struct sockaddr*cliaddr,socklen_t*addrlen);返回:非负描述

30、字(connfd)OK;-1出错;accept函数由TCP服务器调用;从已完成连接队列头返回下一个已完成连接;如果该队列空,则进程进入睡眠状态。函数返回的套接字为已连接套接字,应与监听套接字区分开来 该函数最多:一个既可能是新套接字也可能是错误指示的整数,一个客户进程的协议地址(由cliaddr所指),以及该地址的大小(这后两个参数是值结果参数);也就是说,服务器可以通过参数cliaddr来得到请求连接并获得成功的客户的地址和端口号;基本套接字函数close#include int close(int sockfd);返回:0OK;-1出错;close函数缺省功能是将套接字做上“已关闭”标记,

31、并立即返回到进程。这个套接字不能再为该进程所用。正常情况下,close将引发向TCP的四分节终止序列,但在终止前将发送已排队的数据;如果套接字描述符访问计数在调用close后大于0(在多个进程共享同一个套接字的情况下),则不会引发TCP终止序列(即不会发送FIN分节);基本套接字函数-shutdown#include int shutdown(int sockfd,int howto);返回:0OK;-1出错,并置相应的errno的值;该函数立即发送FIN分节(无论其访问计数是否大于0)。shutdown根据参数howto关闭指定方向的数据传输;SHUT_RD:关闭连接的读这一半,不再接收套接

32、字中的数据且现留在接收缓冲区的数据作废;SHUT_WR:关闭连接的写这一半(半关闭),当留在套接字发送缓冲区中的数据都被发送,后跟tcp连接终止序列,不管访问计数是否大于0;此后将不能在执行对套接字的任何写操作;SHUT_RDWR:连接的读、写都关闭,这等效于调用shutdown两次,一次调用是用SHUT_RD,第二次用SHUT_WR。数据数据FIN数据和FIN的确认数据数据FIN数据和FIN的确认writewriteshutdownRead返回大于0Read返回大于0Read返回0writewritecloseRead返回大于0Read返回0Read返回大于0客户服务器调用shutdown关

33、闭一半TCP连接基本套接字函数read#include int read(int fd,char*buf,int len);返回:大于0读写字节大小;-1出错;调用函数read时,有如下几种情况:套接字接收缓冲区接收数据,返回接收到的字节数;tcp协议收到FIN数据,返回0;tcp协议收到RST数据,返回1,同时errno为ECONNRESET;进程阻塞过程中接收到信号,返回1,同时errno为EINTR。read(connfd,buff,strlen(buff);基本套接字函数write#include int write(int fd,char*buf,int len);返回:大于0读写字

34、节大小;-1出错;调用函数write,有如下几种情况:套接字发送缓冲区有足够空间,返回发送的字节数;tcp协议接收到RST数据,返回1,同时errno为ECONNRESET;进程阻塞过程中接收到信号,返回1,同时errno为EINTR。write(connfd,buff,strlen(buff);数据传输函数send#include#include ssize_t send(int fd,const void*msg,size_t len,int flags);返回:非0发送成功的数据长度;-1出错;flags 是传输控制标志,其值定义如下:0:常规操作,如同write()函数 MSG_OOB

35、,发送带外数据(TCP紧急数据)。MSG_DONTROUTE:忽略底层协议的路由设置,只能将数据发送给与发送机处在同一个网络中的机器上。数据传输函数recv#include#include ssize_t recv(int fd,void*buf,size_t len,int flags);返回:大于0表示成功接收的数据长度;0:对方已关闭,-1:出错。flags是传输控制标志,其值定义如下:0:常规操作,如同read()函数;MSG_PEEK:只查看数据而不读出数据,后续读操作仍然能读出所查看的该数据;MSG_OOB:忽略常规数据,而只读带外数据;MSG_WAITALL:recv函数只有在将

36、接收缓冲区填满后才返回。TCP套接字编程实现TCP套接字基本步骤分为服务器端和客户端两部分:服务器端 创建套接字;绑定套接字;设置套接字为监听模式,进入被动接受连接状态;接受请求,建立连接 读写数据 终止连接TCP套接字编程(cont.)客户端步骤 创建套接字 与远程服务器建立连接 读/写数据;终止连接TCP服务器模板int main(void)int sockfd,connect_sock;if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1)perror(“create socket failed.”);exit(-1);/*bind sockfd to s

37、ome address*/*listen*/loop if(connect_sock=accept(sockfd,NULL,NULL)=-1)perror(“Accept error.”);exit(-1);/*read and process request*/close(connect_sock);close(sockfd);TCP客户模板/*include some header files*/int main(void)int sockfd;if(sockfd=socket(AF_INET,SOCK_STREAM,0)=-1)perror(“Create socket failed.”

38、);exit(-1);/*connect to server*/*send requst and receive response*/close(sockfd);TCP套接字例程 采用客户/服务器模式,完成下列功能:客户根据用户提供的IP地址,连接相应的服务器;服务器等待客户的连接,一旦连接成功,则显示客户的IP地址,并发欢迎信息给客户;客户接收服务器发送的信息并显示;三种异常情况 下面我们考虑在以下三种异常情况发生后,tcp客户服务器程序的反映;服务器主机崩溃 服务器主机崩溃后重启 服务器主机关机。服务器主机崩溃 服务器主机崩溃时,已有的网络连接上发不出任何东西。同时假设应用程序发出数据后,

39、然后阻塞于从套接字读取响应。由于服务器主机崩溃,因此客户tcp会持续重传数据分节,试图从服务器接收一个ACK:源自Berkeley的实现将重传12次。当客户tcp最终放弃时,返回给客户一个错误,此时错误是ETIMEDOUT,或者是因为中间路由器判定服务器主机不可达,且以一个目的地不可达的ICMP消息响应,则错误是EHOSTUNREACH或ENETUNREACH。通过设置套接字选项可以更改tcp持续重传等待的超时时间。服务器主机崩溃后重启 在这种情况下,如果客户在主机崩溃重启前不主动发送数据,那么客户是不会知道服务器已崩溃的。在服务器重启后,客户向服务器发送一个数据分节;由于服务器重启后丢失了以

40、前的连接信息(尽管在服务端口上有进程监听,但连接套接字所在的端口无进程等待),因此导致服务器主机的tcp响应RST;当客户tcp收到RST,向客户返回错误,ECONNRESET 如果客户对服务器的崩溃情况很关心,即使客户不主动发送数据也这样,就需要其他技术支持(如套接口选项SO_KEEPALIVE或某些客户服务器心跳函数)。服务器主机关机 当Linux主机关机时,由init进程给所有运行的进程发信号SIGTERM(我们的服务器程序可以捕获该信号,并在信号处理程序中正常关闭网络连接)。如果服务器程序忽略了SIGTERM信号,则init进程会等待一段固定的时间(通常是5s20s),然后给所有还在运

41、行的程序发信号SIGKILL(该信号不能由服务器程序捕获);服务器将由信号SIGKILL终止,其终止时,所有打开的描述字被关闭,这导致向客户发送FIN分节;客户收到FIN分节后,能推断出服务器将终止服务。UDP套接字编程UDP套接字编程实现UDP套接字基本步骤分为服务器端和客户端两部分:服务器端 建立UDP套接字;绑定套接字到特定地址;等待并接收客户端信息;处理客户端请求;发送信息回客户端;关闭套接字;UDP套接字编程(Cont.)客户端步骤 建立UDP套接字;发送信息给服务器;接收来自服务器的信息;关闭套接字UDP套接字编程(Cont.)UDP数据传输函数sendto#include#inc

42、lude ssize_t sendto(int sockfd,const void*msg,size_t len,int flags,const struct sockaddr*to,int tolen);返回:大于0成功发送数据长度;-1出错;UDP套接字使用无连接协议,因此必须使用sendto函数,指明目的地址;flags是传输控制标志,其值定义如下:0:常规操作,如同write()函数;MSG_OOB:发送带外数据;MSG_DONTROUTE:忽略底层路由协议,直接发送。UDP数据传输函数recvfrom#include#include ssize_t recvfrom(int sock

43、fd,void*buf,size_t len,int flags,struct sockaddr*from,int*fromlen);返回:大于0成功接收数据长度;-1出错;UDP套接字使用无连接协议,因此必须使用recvfrom函数,指明源地址;flags是传输控制标志,其值定义如下:0:常规操作,如同read()函数;MSG_PEEK:只察看数据而不读出数据;MSG_OOB:忽略常规数据,而只读取带外数据;from 和 fromlen 是“值结果”参数。内核长度套接口地址结构用户进程结果值 当函数被调用时,结构大小是一值,当函数返回时,结构大小又是一个结果,这种参数类型叫值-结果参数。参数

44、是一个整型指针。bind(int sockfd,const struct sockaddr*addr,socklen_len len)recvfrom(int sockfd,void*buf,size_t len,int flags,struct sockaddr*from,int*fromlen)值-结果参数说明UDP服务器模板#include#include#inlcude int main(void)int socketfd;if(sockfd=socket(AF_INET,SOCK_DGRAM,0)=-1)perror(“Create socket failed.”);exit(1);

45、/*Bind socket to address*/loop /*receive and process data from client*/*send resuts to client*/close(sockfd);UDP客户模板#include#include#inlcude int main(void)int sockfd;if(sockfd=socket(AF_INET,SOCK_DGRAM,0)=-1)perror(“Create socket failed.”);exit(1);/*send data to the server*/*receive data from the se

46、rver*/close(sockfd);UDP套接字例程 本例程分为服务器和客户两部分,主要完成如下功能:服务器循环接收客户发来的消息,并显示客户IP地址和相应消息;如果服务器收到”quit“,则退出循环,并关闭套接字;客户向服务器发送消息,并接收服务器响应,显示该消息,并关闭套接字。并发服务器目录 服务器分类技术 进程与线程 多进程服务器 多线程服务器并发服务器服务器分类 按连接类型分类 面向连接的服务器(如tcp)面向无连接的服务器(如udp)按处理方式分类 迭代服务器 并发服务器迭代服务器 vs.并发服务器绑定地址监听连接接收连接处理连接断开连接接收请求处理请求返回响应绑定地址监听连接接

47、收连接创建子进程关闭连接套接字处理连接关闭连接套接字终止子进程关闭监听套接字服务器主进程服务器子进程TCP迭代服务器TCP并发服务器“进程”基本概念 进程定义了一个计算的基本单元,可以认为是一个程序的一次运行。它是一个动态实体,是独立的任务。它拥有独立的地址空间、执行堆栈、文件描述符等。每个进程拥有独立的地址空间,进程间正常情况下,互不影响,一个进程的崩溃不会造成其他进程的崩溃。当进程间共享某一资源时,需注意两个问题:同步问题和通信问题。创建进程#include#include pid_t fork(void)返回:父进程中返回子进程的进程返回:父进程中返回子进程的进程ID,子进程返回子进程返

48、回0,-1出错出错 fork后,子进程和父进程继续执行后,子进程和父进程继续执行fork()函数后的指令。()函数后的指令。子进程是父进程的副本。子进程拥有父进程的数据空间、子进程是父进程的副本。子进程拥有父进程的数据空间、堆栈的副本。但父、子进程并不共享这些存储空间部分。堆栈的副本。但父、子进程并不共享这些存储空间部分。如果代码段是只读的,则父子进程共享代码段。如果父子如果代码段是只读的,则父子进程共享代码段。如果父子进程同时对同一文件描述字操作,而又没有任何形式的同进程同时对同一文件描述字操作,而又没有任何形式的同步,则会出现混乱的状况;步,则会出现混乱的状况;父进程中调用父进程中调用fo

49、rk之前打开的所有描述字在函数之前打开的所有描述字在函数fork返回返回之后子进程会得到一个副本。之后子进程会得到一个副本。fork后,父子进程均需要将后,父子进程均需要将自己不使用的描述字关闭。自己不使用的描述字关闭。创建进程(cont.)#include#include pid_t vfork(void);该系统调用基本上与该系统调用基本上与fork相同,在相同,在BSD3.0中开始出现,主要中开始出现,主要为了解决为了解决fork昂贵的开销。昂贵的开销。两者的基本区别在于当使用两者的基本区别在于当使用vfork()创建新进程时,父进程将创建新进程时,父进程将被暂时阻塞,而子进程则可以借用

50、父进程的地址空间,直到被暂时阻塞,而子进程则可以借用父进程的地址空间,直到子进程退出,至此父进程才继续执行。子进程退出,至此父进程才继续执行。终止进程终止进程 进程的终止存在两个可能:进程的终止存在两个可能:父进程先于子进程终止(父进程先于子进程终止(init进程领养)进程领养)子进程先于主进程终止子进程先于主进程终止 对于后者,系统内核为子进程保留一定的状态对于后者,系统内核为子进程保留一定的状态信息:进程信息:进程ID、终止状态、终止状态、CPU时间等;当父时间等;当父进程调用进程调用wait或或waitpid函数时,获取这些信息;函数时,获取这些信息;(什么叫(什么叫“僵尸进程僵尸进程”

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(全套课件·《Linux/UNIX网络编程》1.ppt)为本站会员(三亚风情)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|