2.1应用层协议原理
2.1.1网络应用程序体系结构:客户-服务器结构 , 对等(p2p)结构(自扩展性)、
2.1.2进程通信:通过交换报文。
客户和服务器进程;
进程与计算机网络的接口(套接字即应用程序编程接口API);
进程寻址:需要①主机的地址(因特网使用IP)②定义目的主机中接收进程的标识符(端口号)
2.1.3 可供应用程序使用的运输服务(运输协议)
可靠数据传输:即实现数据完整正确的交付给另一端
吞吐量:带宽敏感的应用;弹性应用;有些运输层协议可以保证吞吐量
定时 :运输层协议也能保证例如发送方注入套接字中的每个比特到达接收方的时间不迟于100ms
安全性:运输层加密解密
2.1.4因特网提供的运输服务(TCP/UDP)
TCP:面向连接,握手后一个TCP连接会在两个进程的套接字之间建立(全双工) ; 可靠;拥塞控制
安全套接字层SSL:是TCP的一种加强,在应用层实现
UDP:无连接;不可靠;没有拥塞控制
TCP,UDP都不提供安全保护
2.1.5应用层协议:定义了端到端的应用程序如何相互传递报文,还定义了:
2.2 Web与HTTP
2.2.1HTTP概况
Web的应用层协议是HTTP(一个客户程序和一个服务器程序)
Web页面由多个对象组成,通过URL引用
HTTP服务器不保存用户的状态信息,所以HTTP是无状态协议
2.2.2非持续连接(每个请求/响应都使用一个单独的TCP)和持续连接(多个共用)
持续连接甚至可以将同一台服务器上的多个Web页面在发送给同一客户的时候可以在单个TCP上进行
2.2.3HTTP报文格式
请求报文:
第一行叫做请求行:方法字段(get <- 大多数 post put 等) URL字段 HTTP版本字段
后面的叫做首部行:指明对象所在主机
第三行表示不使用持续连接
User-Agent:指明用户代理,即向服务器发送请求的浏览器类型
AC-LAN:表示想得到的对象的语法版本
实体主体在POST方法中用来保存表单的输入值
Get方法也可以填写表单,如
HTTP响应报文:
2.2.4用户与服务器的交互:cookie
cookie允许站点对用户进行追踪
在请求/响应报文的首部行都有Cookie行,用户端由浏览器管理一个Cookie文件,Web服务器端也在数据库中存储识别Cookie
2.2.5Web缓存器(代理服务器)
通过设置Web缓存器降低平均时延比升级物理链路和带宽代价低
2.2.6条件Get方法(检测Web缓存器中的对象版本是否最新)
Get方法 + 那么这个HTTP请求报文就是一个条件Get请求报文
条件Get:
Web响应条件Get:304说明服务器端的对象没被修改过,缓存器可以发给客户
2.3文件传输协议FTP
两个tcp连接:控制连接,数据连接
控制信息带外传送,而HTTP是带内传送
控制连接在整个会话期间是连续的,数据连接是不连续的
2.4电子邮件
用户代理,邮件服务器,
简单邮件传输协议SMTP:基于TCP,一般不使用中间邮件服务器
HTTP:拉
SMTP:推 , 报文为7比特ascii码
2.4.3邮件报文格式和MIME
报文自身首部行:from,to,subject
2.4.4邮件访问协议
POP3:特许,事务处理,更新
IMAP:比POP3增加了 服务器端文件夹功能,部分获取报文功能
2.5因特网的目录服务
2.5.1DNS提供的服务
完成主机名到IP地址的转换
完成主机别名到主机名的转换
邮件服务器别名:将邮件服务器别名解析为规范主机名与IP地址
负载分配:循环分配冗余服务器实现负载分配
2.5.2DNS的工作原理
分布式层次数据库:根DNS服务器,顶级域服务器TLD,权威DNS服务器
DNS缓存类似代理服务器得保存主机名/IP映射(通常为2天)
2.5.3DNS记录和报文
2.6P2P应用
P2P体系结构的扩展性
P2P的最小分发时间
BitTorrent协议:Tirrent(洪流)
每个洪流具有一个基础设施节点成为追踪器
基于TCP/UDP的socket编程
实现简单的server端与client端连续通信(基于LINUX - C++)
client端:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main()
{
//创建套接字
//向服务器(特定的IP和端口)发起请求
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充
serv_addr.sin_family = AF_INET; //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址
serv_addr.sin_port = htons(1234); //端口
while(1)
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
char str1[111] ;
scanf("%s",str1);
write(sock,str1,sizeof(str1));
printf("SEND SUCCESSFULLY\n");
// //读取服务器传回的数据
char buffer[40];
read(sock, buffer, sizeof(buffer)-1);
//
printf("Message form server: %s\n", buffer);
close(sock);
}
//关闭套接字
return 0;
}
server端:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
//创建套接字
int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//创建一个参数体
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充
serv_addr.sin_family = AF_INET; //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址
serv_addr.sin_port = htons(1234); //端口
bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));//将套接字和IP、端口绑定
listen(serv_sock, 20);//进入监听状态,等待用户发起请求
//接收客户端请求
while(1)
{
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size = sizeof(clnt_addr);
int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
char str1[50];
read(clnt_sock, str1, sizeof(str1)-1);
printf("Server GET : %s\n",str1);
//向客户端发送数据
char str[] = "Server has been got";
write(clnt_sock, str, sizeof(str));
close(clnt_sock);
}
//关闭套接字
close(serv_sock);
return 0;
}