计算机网络(第三章,网络应用(下))

计算机网络(第三章,网络应用(下))

这是本人初学《计算机网络》做的一些笔记,随着深入理解与学习,会对笔记进行改进

P2P应用

P2P应用_原理与文件分发

纯P2P架构:没有服务器;任意端系统之间直接通信;节点阶段性接入Internet;节点可能更换IP地址
在这里插入图片描述对于C/S:
服务器串行地发送N个副本,时间为:NF/us
客户机i需要F/di时间下载
所以从一个服务器向N个节点分发一个文件需要dcs=max{NF/us,F/min{di}}的时间

对于P2P:
服务器必须发送一个副本:F/us
客户机i需要F/di时间下载
总共需要下载NF比特
最快的可能上传速度为us+Σui
所以一个服务器向N个节点分发一个文件需要dP2P=max{F/us,F/min{di},NF/(us+Σui)}的时间

BitTorrent

  • 文件划分为256KB的chunk
  • 节点加入torrent
    没有chunk,但是会逐渐积累;
    向tracker注册以获得节点清单,与某些节点(“邻居”)建立连接;
  • 下载的同时,节点需要向其他节点上传chunk
  • 节点可能加入或离开
  • 一旦节点获得完整的文件,它可能(自私地)离开或(无私地)留下
  • 获取chunk
    给定任一时刻,不同的节点持有文件的不同chunk集合
    节点(Alice)定期查询每个邻居所持有的chunk列表
    节点发送请求,请求获取缺失的chunk(稀缺优先)
  • 发送chunk:tit-for-tat
    Alice向4个邻居发送chunk,正在向其发送chunk,速率最快的4个(每10s重新评估top4)
    每30s随机选择一个其他节点,向其发送chunk(新选择的节点可能加入top4;“optimistically unchoke”)

P2P应用_索引

P2P系统的索引:信息到节点位置(IP地址+端口号)的映射
例如:

  • 文件共享(电驴):
    利用索引动态跟踪节点所共享的文件的位置;
    节点需要告诉索引它拥有哪些文件;
    节点搜索索引,从而获知能够得到哪些文件
  • 即时消息(QQ):
    索引负责将用户名映射到位置;
    当用户开启IM应用时,需要通知索引它的位置
    节点检索索引,确定用户的IP地址

集中式索引
Napster最早采用这种设计:
1)节点加入时,通知中央服务器:IP地址,内容
2)Alice查找“Hey Jude”
3)Alice从Bob处请求文件

集中式索引的问题:单点失效问题;性能瓶颈;版权问题

洪泛式查询
在这里插入图片描述
层次式覆盖网络
介于集中式索引和洪泛式查询之间的方法,每个节点或者是一个超级节点,或者被分配一个超级节点(节点和超级节点间维持TCP连接;某些超级节点对之间维持TCP连接),超级节点负责跟踪子节点的内容
在这里插入图片描述

Socket编程

API:Application Programming Interface 应用编程接口


WSAStartup

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);

使用Socket的应用程序在使用Socket之前必须首先调用WSAStartup函数

两个参数:

  • 第一个参数指明程序请求使用的WinSock版本,其中高位字节指明副版本、低位字节指明主版本(十六进制整数,例如0x102表示2.1版本)
  • 第二个参数返回实际的WinSock的版本信息(指向WSADATA结构指针)

例如:使用2.1版本的WinSock的程序代码段

wVersionRequested = MAKEWORD(2,1);
err = WSAStartup(wVersionRequested, &wsaData);

WSACleanup

int WSACleanup(void);

应用程序在完成对请求的Socket库的使用,最后要调用WSACleanup函数;解除与Socket库的绑定;释放Socket库所占的系统资源


socket

sd = socket(protofamily, type, proto);

创建套接字
操作系统返回套接字描述符(sd)
第一个参数(协议族):
protofamily=PF_INET(TCP/IP)
第二个参数(套接字类型):
type = SOCK_STREAM, SOCK_DGRAM or SOCK_RAW (TCP/IP)

例如:创建一个流套接字的代码段

struct protoent *p;
p = getprotobyname("tcp");
SOCKET sd = socket(PF_INET, SOCK_STREAM, p->p_proto);

Socket面向TCP/IP:流套接字,特点:可靠、面向连接、字节流传输、点对点

Socket面向UDP:数据报套接字,特点:不可靠、无连接、数据报传输


Closesocket

int closesocket(SOCKET sd);

关闭一个描述符为sd的套接字

如果多个进程共享一个套接字,调用closesocket将套接字引用数量减1,减至0才关闭

一个进程中的多线程对一个套接字的使用无计数,如果进程中的一个线程调用closesocket将一个套接字关闭,该进程中的其他线程也将不能访问该套接字

返回值:0(成功);SOCKET_ERROR(失败)


bind

int bind(sd, localaddr, addrlen);

绑定套接字的本地端点地址(IP地址+端口号)

参数:
套接字描述符(sd);
端点地址(localaddr):结构sockaddr_in

客户程序一般不必调用bind函数

服务器端需要调用bind函数来熟知端口号

地址通配符:INADDR_ANY


listen

int listen(sd, queuesize);

置服务器端的流套接字处于监听状态:
仅服务器端调用;
仅用于面向连接的流套接字;

设置连接请求队列大小(queuesize)

返回值:0(成功);SOCKET_ERROR(失败)


connect

connect(sd, saddr, saddrlen);

客户程序调用connect函数来使客户套接字(sd)与特定计算机的特定端口(saddr)的套接字(服务)进行连接

仅用于客户端

可用于TCP客户端,也可用于UDP客户端:
TCP客户端:建立TCP连接
UDP客户端:指定服务器端点地址


accept

newsock = accept(sd, caddr, caddrlen);

服务程序调用accept函数从处于监听状态的流套接字sd的客户连接请求队列中取出排在最前的一个客户请求,并创建一个新的套接字来与客户套接字创建连接通道(仅用于TCP套接字,仅用于服务器)

利用新创建的套接字(newsock)与客户通信


send,sendto

send(sd, *buf, len, flags);

sendto(sd, *buf, len, flags, destaddr, addrlen);

send函数用于TCP套接字(客户端与服务器)或调用了connect函数的UDP客户端套接字

sendto函数用于UDP服务器端套接字与未调用connect函数的UDP客户端套接字


recv,recvfrom

recv(sd, *buffer, len, flags);

recvfrom(sd, *buf, len, flags, senderaddr, saddrlen);

recv函数从TCP连接的另一端接收数据,或者从调用了connect函数的UDP客户端套接字接收服务器发来的数据

recvfrom函数用于从UDP服务器端套接字与未调用connect函数的UDP客户端套接字接收对端数据


setsockopt,getsockopt

int setsockopt(int sd, int level, int optname, *optval, int optlen);

int getsockopt(int sd, int level, *optname, *optval, socklen_t *optlen);

==setsockopt()==函数用来设置套接字sd的选项参数

==getsockopt()==函数用于获取任意类型、任意状态套接口的选项当前值,并把结果存入optval


Socket API函数小结

函数名功能
WSAStartup初始化socket库(仅对WinSock)
WSACleanup清除/终止socket库的使用(仅对WinSock)
socket创建套接字
connect“连接”远端服务器(仅用于客户端)
closesocket释放/关闭套接字
bind绑定套接字的本地IP地址和端口号(通常客户端不需要)
listen置服务器端TCP套接字为监听模式,并设置队列大小(仅用于服务器端TCP套接字)
accept接受/提取一个连接请求,创建新套接字,通过新套接字(仅用于服务器端的TCP套接字)
recv接收数据(用于TCP套接字或连接模式的客户端UDP套接字)
recvfrom接受数据报(用于非连接模式的UDP套接字)
send发送数据(用于TCP套接字或连接模式的UDP套接字)
sendto发送数据报(用于非连接模式的UDP套接字)
setsockopt设置套接字选项参数
getsockopt获取套接字选项参数

关于网络字节顺序

TCP/IP定义了标准的用于协议头中的二进制整数表示:网络字节顺序

某些Socket API函数的参数需要存储为网络字节顺序(如IP地址,端口号等)

可以实现本地字节顺序与网络字节顺序间转换的函数:

htons:本地字节顺序→网络字节顺序(16bits)

ntohs:网络字节顺序→本地字节顺序(16bits)

htonl:本地字节顺序→网络字节顺序(32bits)

ntohl:网络字节顺序→本地字节顺序(32bits)


4种基本类型服务器:
循环无连接服务器
循环面向连接服务器
并发无连接服务器
并发面向连接服务器

循环无连接服务器基本流程:
1.创建套接字
2.绑定端点地址(INADDR_ANY+端口号)
3.反复接收来自客户端的请求
4.遵循应用层协议,构造响应报文,发送给客户

其中服务器端不能使用connect()函数
无连接服务器使用sendto()函数发送数据
调用recvfrom()函数接收数据时,自动提取

循环面向连接服务器基本流程:
1.创建(主)套接字,并绑定熟知端口号
2.设置(主)套接字为被动监听模式,准备用于服务器
3.调用accept()函数接收下一个连接请求(通过主套接字),创建新套接字用于与该客户建立连接
4.遵循应用层协议,反复接收客户请求,构造并发送响应(通过新套接字)
5.完成为特定客户服务后,关闭与该客户之间的连接,返回步骤3

并发无连接服务器基本流程:
主线程1:创建套接字,并绑定熟知端口号
主线程2:反复调用recvfrom()函数,接收下一个客户请求,并创建新线程处理该客户响应
子线程1:接收一个特定请求
子线程2:依据应用层协议构造响应报文,并调用sendto()发送
子线程3:退出(一个子线程处理一个请求后即终止)

并发面向连接服务器基本流程:
主线程1:创建(主)套接字,并绑定熟知端口号
主线程2:设置(主)套接字为被动监听模式,准备用于服务器
主线程3:反复调用accept()函数接收下一个连接请求(通过主套接字),并创建一个新的子线程处理该客户响应
子线程1:接收一个客户的服务请求(通过新创建的套接字)
子线程2:遵循应用层协议与特定客户进行交互
子线程3:关闭/释放连接并退出(线程终止)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值