1、 网络应用程序设计包括:通信客户端的设计通信服务器端的设计(*)网络编程模型C/S模型网络应用的标准模型是C/S模型C/S模型是非对称模型,主要体现在 软件结构和工作过程上。B/S模型随着Internet技术的兴起,B/S模型是对C/S模型的一种变化或者改进。B/S模型的特点:“瘦客户端、 胖服务器端”。C/S与B/S 模式主要区别包括:硬件环境不同、安全要求不同、程序架构不同、软件重用不同、系统维护不同等方面。服务器模型 循环服务器任一时刻只处理一个客户机请求,处理请求过程中下一请求等待 节省服务器资源,响应时间长,适合处理非耗时请求 并发服务器并发执行,每收到一个连接请求创建一个进程处理该
2、连接,服务器继续等待下一连接 响应速度快,占用系统资源多 典型C/S程序模型框架简单C/S模型程序示例client.cserver.c网络协议基于TCP/IP 的4 层协议Internet协议(IP)功能完成数据包发送和接收特点非面向连接、不保证数据包可靠到达IP协议数据包格式(IPv4)网络协议用户数据报协议( UDP )功能在IP协议基础上传送数据包特点非面向连接,不可靠到达UDP数据包格式应用场合交易型应用,不要求可靠传输网络协议传输控制协议( TCP )功能在IP协议基础上传送数据包特点面向连接,数据包可靠有序到达具有流量控制能力全双工通道应用场合大部分需要可靠数据传输的应用TCP数据
3、包格式SYN位 请求建立连接 ACK位应答标志 FIN位请求关闭连接 RST位请求复位连接 传输控制协议( TCP )建立TCP连接(“三次握手”)传输控制协议( TCP )关闭TCP连接(“四次握手”)传输控制协议( TCP )标识一条TCP连接的4个信息(“四位一体”)本地IP本地端口对方IP对方端口网络协议消息控制协议( ICMP )功能通常由路由器产生,报告网络传输错误特点封装在IP数据包的数据部分传输ICMP数据包格式(P8,表1-1)ICMP数据包的应用网络探测命令ping网络协议标准Internet服务ftphttppop3smtp作业(P28) 3简述 OSI七层模型和TCP/
4、IP模型的异同。 4简述客户机/服务器的运行模式。 5服务器可以分为哪两个类型? 7简述 Client/Server和Browser/Server的区别。 8在计算机网络中的服务类型有哪些? 10名词解释:地址;连接;相关;带外数据;缓存;分组交换。 11TCP连接的特点和基本流程是什么?何谓“三次握手”?网络应用程序设计unit02 基本socket函数基于TCP编程模型网络编程模型基于有连接网络程序的执行过程 服务程序启动客户程序启动客户端与服务器建立连接客户端发送请求服务器处理请求,返回响应服务器断开连接,等待下一个请求 套接字是一种网络API,程序员可以用之开发网络程序。套接字类型套接
5、字支持多种通信协议: Unix:Unix 系统内部协议 INET:IP版本4 INET6:IP 版本6Linux支持多种套接字类型,即应用程序希望的通信服务类型 SOCKET_STREAM:双向可靠数据流,对应TCP SOCKET_DGRAM:双向不可靠数据报,对应UDP SOCKET_RAW:是低于传输层的低级协议或物理网络提供的套接字类型,可以访问内部网络接口。例如接收和发送ICMP报字节排序函数 为保证”大端“和”小端“字节序的机器之间能相互通信,需在发送多字节整数时,将主机字节序转换成网络字节序,或反之。字节排序函数(续)#include uint16_t htons(uint16_t
6、 hostshort)uint32_t htonl(uint32_t hostlong)均返回:网络字节序值uint16_t ntohs(uint16_t netshort)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, siz
7、e_t nbytes); /*返回0则相同,非0不相同*/上述三个函数源自BSDvoid *memset(void *dest, int c, size_t len);void *memcpy(void *dest, const void *src, size_t nbytes);int memcmp(const void *ptr1, const void *ptr2, size_t nbytes)上述三个函数属于ANSI C地址转换函数将点分十进制数串转换成32位网络字节序二进制值。int inet_aton(const char *cp, struct in_addr *inp);返回:
8、1-串有效,0-串有错in_addr_t inet_addr(const char *cp);返回:若成功,返回32位二进制的网络字节序地址,若有错,则返回一个 常值INADDR_NONE(32位均为1 ). 过时函数过时函数 inet_aton函数将cp所指的字符串( 点分十进制数串,如192.168.0.1)转换成32位的网络字节序二进制,并通过指针inp 来存储。这个函数需要对字符串所指的地址进行有效性验证。但如果cp为空,函数仍然成功,但不存储任何结果。 inet_addr进行相同的转换,但不进行有效性验证,也就是说,所有2 32种可能的二进制值对inet_addr函数都是有效的。地址
9、转换函数(续)#include char *inet_ntoa(struct in_addr inaddr);返回:指向点分十进制数串的指针 函数inet_ntoa将32位的网络字节序二进制IPv4 地址转换成相应的点分十进制数串。但由于返回值所指向的串留在静态内存中,这意味着函数是不可重入的。 需要注意的是这个函数是以结构为参数的,而不是指针。 上述三个地址转换函数都只能处理IPv4协议,而不能处理IPv6地址。地址转换函数(续)int inet_pton(int family, const char *strptr, void *addrptr);返回:1-成功,0输入无效,-1:出错co
10、nst char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);返回:指向结果的指针成功,NULL出错字母p 和n 分别代表presentation(地址的表达格式)和numeric(数值格式)。 family参数可以是AF_INET,也可以是AF_INET6。 长度参数len是目标的大小,如果太小无法容纳表达格式结果,则返回一个空指针。另外,目标指针调用前必须先由调用者分配空间。socket(套接字)网络传输的端节点支持多种协议 UNIX、INET、IPX支持多种类型 流式(STREAM)数据报(D
11、GRAM)原始(RAW)创建网络端点socketint socket (int family, int type, int protocol)功能:创建socket描述符参数:(P34表2-1描述了可能的参数值)family(协议簇): AF_INET、 AF_UNIXtype(类型):SOCK_STREAM、SOCK_DGRAM、SOCK_RAWprotocol(协议):默认为 0返回值:0socket描述符, -1失败, 系统全局变量errno为错误代码创建网络端点socket(),其返回值赋值给 监/侦听套接字。socket数据结构socket地址socket地址Linux采用通用soc
12、ket地址兼容各种协议UNIXINETsocket地址TCP/IP协议的socket地址socket地址TCP/IP协议的socket地址常用地址形式(字符串):“127.0.0.1”地址转换函数inet_aton(const char *cp,struct in_addr *inp);char* inet_ntoa(struct in_addr in);字节顺序主机字节顺序(以16位整数0xA130为例)little-endian顺序低字节在前Intel处理器使用little-endianbig-endian顺序高字节在前sun工作站使用big-endian顺序字节顺序网络字节顺序 统一表示
13、方式采用big-endian顺序主机字节顺序和网络字节顺序的转换 unsigned short int htons(unsigned short int hostshort) unsigned long int htonl(unsigned long int hostlong) unsigned short int ntohs(unsigned short int netshort) unsigned long int ntohl(unsigned long int netlong)socket地址基于TCP编程模型绑定服务器地址和端口int bind(int sockfd,struct so
14、ckaddr *myaddr,int addrlen); 功能:绑定本地地址和端口参数:sockfdsocket描述符myaddr自己的地址addrlen地址结构长度返回值:0成功,-1失败,errno为错误代码 绑定服务器地址和端口int bind(int sockfd,struct sockaddr *myaddr,int addrlen);说明服务器和客户端都可以绑定socket地址,但通常客户端不需要绑定自己的socket 地址。不绑定地址时系统自动分配一个端口,并用该端口和本机ip地址填充客户端socket 地址.P36,表2-2 绑定地址和端口号的设置方式(注意INADDR_ANY
15、)绑定服务器地址和端口绑定服务器地址和端口INADDR_ANY绑定任何网络设备接口,适合于多IP主机对于IP地址经常变化的情况也适用P36表2-2基于TCP编程模型基于TCP编程模型如何标识一个连接? (复习P13:图1-14 “四位一体”):IP地址 + 端口号连接服务器int connect(int sockfd,struct sockaddr *servaddr,int addrlen)功能:连接服务器参数:sockfdsocket描述符servaddr服务器地址addrlen地址结构长度返回值:0成功,-1失败,errno为错误代码连接服务器int connect(int sockfd
16、,struct sockaddr *servaddr,int addrlen)说明:对一个socket描述符不能两次使用 connect函数 连接服务器基于TCP编程模型监听端口int listen(int sockfd,int backlog)功能:监听本地地址和端口参数:sockfd已绑定的 socket描述符backlog以完成连接,等待接受的队列长度返回值0成功,-1失败,errno为错误代码 监听端口int listen(int sockfd,int backlog)说明执行listen函数后socket 转换成被动socket ,可以接受连接,TCP协议为每个侦听socket维护两
17、个队列:未完成连接队列和已完成连接队列,backlog指定已完成连接队列的最大长度 监听端口基于TCP编程模型接受客户端连接int accept(int sockfd,struct sockaddr *clientaddr,int addrlen);功能:接受连接参数:sockfdsocket描述符clientaddr客户端地址addrlen地址结构长度返回值0成功,返回新的socket描述符标识已接受的连接 ,其返回值赋值给 连接套接字。-1失败,errno 为错误代码接受客户端连接int accept(int sockfd,struct sockaddr *clientaddr,int a
18、ddrlen);说明accept函数返回的socket描述符是真正可以和客户端通信的socket,服务器的侦听socket只接受连接,不能用于通信 accept函数在没有已完成的连接时将阻塞进程接受客户端连接基于TCP编程模型接收数据int read(int fd,char *buf,int len);功能:从socket读取数据参数:fdsocket描述符buf接收数据缓冲区len要读取数据大小返回值n0 and n#include #include #include #include #include #include 作业(P62)2请给出利用socket 进行面向连接的网络编程模型(
19、服务器端和客户端),并写出简单的程序框架。4网络编程时,为什么要考虑字节顺序问题?8在我们常见的程序或软件中,哪些是基于TCP协议实现的?请给出采用TCP的编程的原因。13.为什么说socket接口的设计者开发的 socket API不仅仅为TCP/IP 网络提供了网络编程接口?网络应用程序设计unit 03 高级socket 函数主要内容域名访问高级socket函数多路复用socket选项域名访问域名系统DNS域名IP地址的别名,便于记忆www. hostent* gethostbyname(const char *name)功能:查询域名对应的IP域名访问域名到IP的转换函数gethos
20、tbyname示例域名访问域名到IP的转换函数查询的结果域名访问 域名到IP的转换函数对同一DNS服务器两次调用gethostbyname返回的IP地址列表顺序不同 在不同的DNS服务器上查询,返回结果不同 查询失败时错误类型保存在全局变量h_errno中,hstrerror可以得到h_errno的描述信息域名访问同时兼容域名和IP的应用程序客户端程序段域名访问同时兼容域名和IP的应用程序地址转换函数addr_conv域名访问IP到域名的转换函数struct hostent *gethostbyaddr(const char *addr,size_t len,int family); 功能:查
21、询IP对应的域名高级socket函数recv和sendint recv(int sockfd,void buf,int len, int flags);int send(int sockfd,void buf,int len,int flags);功能:通过参数控制读写数据参数:sockfdsocket描述符buf发送或接收数据缓冲区len发送或接收数据长度flags发送或接收数据的控制参数返回值:0成功, -1失败高级socket函数recv和send控制参数说明flags=0,相当于read和write函数flags=MSG_DONTROUTE,发送数据不查找路由表,适用于局域网,或同一网
22、段flags=MSG_OOB,接收和发送带外数据flags=MSG_PEEK,接收数据时不从缓冲区移走数据,其他进程调用read或recv仍然可以读到数据flags=MSG_WAITALL,数据量不够时,读操作等待,不返回,但在收到信号,连接端口时仍然会结束。高级socket函数 recv和send 控制参数说明表高级socket函数int shutdown(int sockfd,int howto); 功能:关闭连接参数:sockfdsocket描述符howto指定关闭操作的类型返回值:0成功, -1 失败高级socket函数int shutdown(int sockfd,int howto
23、);说明:howto=0,关闭读通道,丢弃尚未读取的数据,对后来接收到的数据返回确认后丢弃高级socket函数int shutdown(int sockfd,int howto);说明:howto=1,关闭写通道,继续发送缓冲区未发送完的数据,然后发送FIN字段关闭写通道高级socket函数int shutdown(int sockfd,int howto);说明:howto=2,关闭读写通道,任何进程不能再操作这个socketshutdown和close的区别shutdown操作连接通道,其他进程不能再使用已被关闭的通道;close 操作描述符,其他进程仍然可以使用该socket 描述符cl
24、ose关闭应用程序进程与 socket的接口,调用close之后该应用程序进程不能再读写这个socket;shutdown可以只关闭一个通道,另一个通道仍然可以操作。高级socket函数readv和writevrecvmsg和sendmsggetsockname和getpeername多路复用多路复用函数selectint select(int maxfd,fd_set *rdset,fd_set *wrest,fd_set *exset,struct timeval *timeout);功能:检查多个文件描述符(socket描述符)是否就绪,当某一个描述符就绪(可读、可写或发生异常)时函数返
25、回。可以实现输入输出多路复用返回值:有描述符就绪则返回就绪的描述符个数;超时时间内没有描述符就绪返回0;执行失败返回-1。多路复用多路复用函数select参数:maxfd需要测试的描述符的最大值,实际测试的描述符从0maxfd-1 rdset需要测试是否可读的描述符集合(包括处于listen 状态的socket接收到连接请求) wrset需要测试是否可写的描述符集合(包括以非阻塞方式调用connect是否成功) exset需要测试是否异常的描述符集合(包括接收带外数据的socket有带外数据到达) timeout指定测试超时的时间 多路复用多路复用函数selecttimeout参数timeva
26、l结构timeout=NULL,select将永远阻塞直到有一个描述符就绪,或者出现错误(接收到信号)。timeout0,在timeout时间内如果有描述符就绪则返回,否则在 timeout时间后返回0;如果将3个描述符集合都设定为NULL则select相当于sleep 函数,只是时间可以精确到毫秒 timeout=0,select检查完描述符集合后立即返回 多路复用 多路复用函数select 设置描述符集合FD_ZERO(fd_set *fdset)清空描述符集合 FD_SET(int fd,fd_set *fdset)将一个描述符添加到描述符集合 FD_CLR(int fd,fd_set
27、*fdset)将一个描述符从描述符集合中清除 FD_ISSET(int fd,fd_set *fdset)检测一个描述符是否就绪 在设置描述符集合前应该先调用FD_ZERO 将集合清空,每次调用select函数前应该重新设置这3个集合 三个集合中的描述符可以交叉 socket选项设置/获取socket选项函数int getsockopt(int sockfd, int level, int optname, void *optval, sock_len *optlen);int setsockopt(int sockfd, int level, int optname, void *optval, sock_len optlen);功能:获取或设置socket选项返回值: 0成功, -1失败socket选项设置/获取socket选项函数参数:sockfdsocket描述符level选项级别SOL_SOCKET 通用socket 选项 IPPROTO_IPIP选项 IPPROTO_TCPTCP选项 optname选项名称optval选项值 optlen选项值的长度/存放选项值长度的指针 socket选项通用socket选项(P44: 表2-4)