前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >网络编程的一些理论

网络编程的一些理论

作者头像
xcywt
发布2018-01-12 10:01:58
8780
发布2018-01-12 10:01:58
举报
文章被收录于专栏:xcywtxcywt

参考自《VC++深入详解》

  这是我在看书时记录下来的东西。

 注:下面的Socket其实都应该是socket

第14章网络编程

Socket是连接应用程序与网络驱动程序的桥梁,Socket在应用程序中创建,通过绑定与驱动程序建立关系。

此后,应用程序给Socket的数据,由Socket交给驱动程序向网络上发送出去。

计算机从网络上收到与该Socket绑定的IP地址和端口号相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据。

14.1 计算机网络基本知识。

1,最简单的网络形式是由两台计算机组成,就酱

2,网络上主机间通信需要知道另一主机的名字。在Internet上用一个称为IP地址(4个字节)的整数来标识网络设备。

在Internet上,两台主机要通信,双方必须遵守约定的规则,称为协议。

计算机中运行着很多网络通信程序(迅雷、酷狗、浏览器等),要怎么区分呢?端口号:标识在计算机上运行的每一个网络通信程序。所以,指定IP外,还要指定端口号。

IP地址相当于总机号码,而端口号相当于分机号码。

14.1.1 IP地址

IP网络中每台主机必须有唯一的IP地址

IP地址是一个逻辑地址

因特网上的IP地址具有全球唯一性

32位,4字节。常用点分十进制表示,例如:192.168.0.1(每个字节用十进制整数来表示) 

注:127.0.0.1 称为是回送地址,指本地机,一般用来测试使用

14.1.2 协议  P533

为进行网络中的数据交换而建立的规则,标准或约定

不同层具有各自不同的协议。

14.1.5 ISO/OSI 七层参考模型

1,ISO国际标准化组织提出来OSI七层参考模型,将网络的不同功能划分为7层。如下图

从低到高各层的功能分别如下所述:

(1) 物理层:提供二进制传输,确定在通信信道上如何传输比特流

(2) 数据链路层:提供介质访问,加强物理层的传输功能,建立一条无差错的传输线路

(3) 网络层:提供IP寻址和路由。因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输线路

(4) 传输层:为源主机到目的端主机提供可靠的数据传输服务,隔离网络的上下层协议,使得网络应用与下层协议无关

(5) 会话层:在两个相互通信的应用程序之间建立、组织和协调其相互之间的通信

(6) 表示层:处理被传送数据的表示问题,即信息的语法和语义。如有必要,可使用一种通用的数据表示格式,在多种数据表示之间进行切换。

(7) 应用层:为用户的网络应用程序提供网络通信的服务

应注意一下几点:

(1) OSI七层参考模型并不是物理实体存在这七层,这只是一个功能的划分,是一个抽象的网络参考模型

(2) 在进行一个网络通信时,每一层为本次通信提供本层的服务。通信实体的对等层之间不允许直接通信

(3) 各层之间是严格单向依赖

(4) 上层使用下层提供的服务 – Service user

(5) 下层向上层提供服务 – Service provider

2,通信时数据传输的过程:在两个通信实体进行通信时,应用层所发出的数据经过表示层、会话层、传输层、网络层、数据链路层、最终到达物理层,在该层通过物理线路传输给另外一个实体的物理层。

然后,数据再依次向上传递,传递给另一个实体的应用层。

3,对等层通信的实质就是: 对等层实体之间虚拟通信。下层向上层提供服务,实际通信在最底层完成。

干货:对等通信peer-to-peer communication,为了使数据分组从源传送到目的地,源端OSI模型的每一层都必须与目的端的对等层进行通信,这种通信方式称为对等层通信。 在这一过程中,每一层的协议在对等层之间交换信息,该信息成为协议数据单元(PDU)。 简单来理解就是这样,假设主机A要和主机B通信。A的应用层只能与B的应用层交换信息,而不能与B的其他层(比如传输层)交换信息。

4,OSI7层参考模型中的应用层、传输层和网络层所用的协议:

(1) 应用层:远程登录协议Telnet,文件传输协议FTP(下载文件),超文本传输协议HTTP(浏览网页),

域名服务DNS(网址就是域名),简单邮件传输协议SMTP(发送邮件),邮局协议POP3(收取邮件)。

(2) 传输层:传输控制协议TCP:面向连接的可靠的传输协议,通信时要通过三步握手以建立通信双方的连接。

用户数据报协议UDP:无连接、不可靠的传输协议。不需要建立连接,可能会丢失数据,实时性较高。

(3) 网络层:网络协议IP、Internet互联网控制报文协议ICMP,Internet组管理协议IGMP。

14.1.6 数据封装

1,往另外一台计算机发送数据,首先要将该数据打包打包的过程称为封装。

2,封装就是在数据前面加上特定的协议头部,例如:用TCP协议传时,数据到传输层时,就会加上TCP协议头,在到达网络层时,在其前面加上IP协议头。

3,OSI参考模型中,对等协议之间交换的信息单元统称为协议数据单元(PDU)。

4,为了提供服务,下层把上层的PDU作为本层的数据封装,然后加入本层的头部(有点还要加尾部,如数据链路层)。头部的数据中含有数据传输所需的控制信息。

14.1.7 TCP/IP模型

1,起源于美国国防部高级研究规划署的一项研究计划,现在。已经称为Internet上通信的工业标准。

2,OSI参考模型比较复杂,目前应用较多的是TCP/IP模型,该模型包含4个层次:  应用层   传输层   网络层   网络接口层

14.1.8 端口

1,端口是一种抽象的软件结构(包括一些数据结构和I/O缓冲区)。应用程序通过系统调用与某端口建立连接(binding)后,传输层传给该端口的数据都被相应的进程所接收。

相应进程发给传输层的数据都通过该端口输出。

2,端口用一个整数型标识符来表示,即端口号。(0 – 65535,我们在编写网络应用程序时,要为程序指定1024以上的端口号)。

3,端口号跟协议相关,TCP/IP传输层的两个协议TCP和UDP是完全独立的两个软件模块,因此各自的端口号也相互独立。

也就是说基于TCP和UDP协议的不同的网络应用程序,它们可以拥有相同的端口号。

14.1.9 套接字的引入

1,伯克利大学推出一种应用程序访问通信协议的操作系统调用套接字。Socket的出现,使程序员可以很方便的访问TCP/IP,从而开发各种网络应用的程序。

2,套接字存在于通信区域中。通信区域也叫地址族,是一个抽象的概念,主要用于将通过套接字通信的进程的共有特性综合在一起。套接字通常只于同一区域的套接字交换数据。

Windows Socket只支持一个通信区域:网际域(AF_INET),这个域被使用网际协议簇通信的进程使用。

14.1.10 网络字节顺序

1,小端模式:低位存在低地址。(低位先存)

2,大端模式:高位存在低地址。(高位先存)

3,基于Inter的CPU,我们常用的PC机采用的是小端模式,为了保证数据的正确性,在网络协议中需要指定网络字节顺序。

4,TCP/IP协议使用16位整数和32位整数的高位先存格式(大端模式)。

5,在网络中不同主机间进行通信时,要统一采用网络字节顺序。

14.1.11 客户机/服务器模式(C/S)

1,在TCP/IP网络应用中,通信的两个进程间相互作用的主要模式是客户机/服务器模式(客户向服务器提出请求,服务器收到请求后,提供相应的服务)。

2,客户机/服务器模式在操作过程中采取的是主动请求的方式。

首先服务器方要先启动,并根据请求提供相应的服务:

(1) 打开一个通信通道并告知本地主机,它愿意在某一地址和端口上接收客户请求。

(2) 等待客户请求到达该端口

(3) 接收到重复服务请求,处理该请求并发送应答信号。接收到并发服务请求,要激活一个新的进程(或线程)来处理这个客户请求。

新进程(线程)处理此客户请求,并不需要对其他请求做出应答。服务完成后,关闭此新进程与客户的通信链路,并终止。

(4) 返回第二步

(5) 关闭服务器

而客户方:

(1) 打开一个通信通道,并连接到服务器所在主机的特定端口。

(2) 向服务器发送服务请求报文,等待并接收应答:继续提出请求,

(3) 请求结束后关闭通信通道并终止。

14.2 Windows Socket的实现

14.2.1 套接字的类型:

(1)流式套接字(SOCK_STREAM):提供面向连接、可靠的数据传输服务,数据无差错、无重复的发送,且按照发送顺序接收。基于TCP协议实现的

(2)数据报套接字(SOCK_DGRAM):提供无连接服务,数据包以独立包形式发送,不提供无错保证,数据可能丢失或重复,接收顺序混乱。基于UDP协议实现的

(3)原始套接字(SOCK_RAW)

14.2.2 基于TCP的Socket编程

服务器端程序流程如下:

(1) 创建套接字(socket)

(2) 将套接字绑定到一个本地地址和端口上(bind)

(3) 将套接字设为监听模式,准备接收客户请求(listen)

(4) 等待客户机请求到来:当请求到来时,接收连接请求,返回一个新的对应于此次连接的套接字(accept)】

(5) 用返回的套接字和客户端进行通信(send/recv)

(6) 返回,等待另一个客户请求

(7) 关闭套接字

客户端程序流程如下:

(1) 创建套接字(socket)

(2) 向服务器发出连接请求(connect)

(3) 和服务器端进行通信(send/recv)

(4) 关闭套接字

服务器端,调用accept函数时,程序就会等待,等待客户端调用connect函数发出连接请求,然后服务器接收该请求,于是双方就建立了连接。

之后,服务器和客户端就可以通过recv/send进行通信了

客户端不要调用bind,因为服务器需要接收客户端的请求,所以必须告诉本地主机打算在哪个IP地址和哪个端口上等待客户请求,因此必须调用bind来实现这一功能。

客户端发起连接,服务器接收该请求后,在服务器就保存了客户端的IP地址和端口的信息,这样就可以利用所返回的套接字调用recv/send函数与客户端进行通信了。

14.2.3 基于UDP(面向无连接的)socket编程

1,服务器端也叫接收端,先启动的一端称为接收端,发送数据的一段称为发送端,也称客户端。(这个概念好像和Linux的有点不一样)

接收端程序的编写:

(1) 创建套接字(socket)

(2) 将套接字绑定到一个本地地址和端口上(bind)

(3) 等待接收数据(recvfrom) // 不是recv     linux这里也可以发送数据

(4) 关闭套接字

客户端程序的编写:

(1) 创建套接字(socket)

(2) 向服务器发送数据(sendto) // 不是send

(3) 关闭套接字

套接字相当于电话机,IP地址相当于总机号码,端口相当于分机

14.3 相关函数

14.3.1 WSAStartup函数(加载套接字库)

1,利用套接字编程时,第一步要加载套接字库。这个函数有两个功能:

(1) 加载套接字库

(2) 进行套接字库的版本协商,就是确定将使用的socket版本

2,每个WSAStartup成功调用(成功加载winsock动态库以后),在最后都会对应一个WSACleanUp调用,以便释放为该应用分配的资源。

   终止对Winsock动态库的使用。

14.3.2 socket函数:加载库之后,用这个函数创建套接字了

1,原型声明如下啊:

14.3.3 bind函数:创建套接字以后,要将该套接字绑定到本地的某个地址和端口上

1,原型

Int bind(SOCKET s, const struct socketaddr FAR *name, int namelen);

成功返回0,失败返回一个SOCKET_ERROR,错误信息可以在WSAGetLastError函数返回。

s :指定要绑定的套接字

name :指定了该套接字的本地地址信息,由于该地址结构是为所有的地址家族准备的,这个结构可能随所使用的网络协议不同而不同

namelen :指定该地址结构的长度

2,sockaddr结构

struct socketaddr

{

u_short sa_family; // 指定地址家族,对于TCP/IP协议的套接字,必须设置为 AF_INET

char sa_data[14];  // 仅仅表示要求一块内存分配区,起到占位的作用

};

3,在基于TCP/IP的socket编程过程中,可以用sockaddr_in结构替换sockaddr

struct socketaddr_in

{

short sin_family; // 地址族,对于IP地址,这个值一直是 AF_INET

unsigned short sin_port; // 指定将要分配给套接字的端口

struct in_addr sin_addr; // 套接字的主机IP地址

char sin_zero[8];// 填充数

};

4,sockaddr_in结构中的sin_addr成员类型是in_addr,这个实际上是一个联合(union),

  通常利用这个结构将一个点分十进制格式的IP地址转换为u_long类型。

14.3.4 inet_addr和inet_ntoa函数

1,将IP地址指定为INADDR_ANY,允许套接字向任何分配给本地机器的IP地址发送或接收数据。

2,每个机器只有一个IP,但有的机器有多个网卡,每个网卡都会有自己的IP地址。

3,如果想让套接字使用多个IP中的一个地址,就必须指定实际地址,可以用inet_addr函数来实现。

4,unsigned long inet_addr(const char FAR *cp);

 Cp:指定了以点分十进制格式表示的IP地址

5,char FAR *inet_ntoa(struct in_addr in);

这个函数会完成相反的转换,接收一个in_addr结构体类型的参数并返回一个以点分十进制表示的IP地址字符串

14.3.5 listen函数:将指定的套接字设置为监听模式

1,int listen(SOCKET s, int backlog);

s:套接字描述符

backlog:等待连接队列的最大长度

2,backlog是为了设置等待连接队列的最大长度,不是在一个端口上同时可以进行连接的数目。

(假如设为2,有3个请求同时来的时候,前两个会放到等待请求连接队列中,然后由应用程序一次为这些请求服务,第三个连接请求被拒绝了)

14.3.6 accept函数:接收客户端发送的连接请求

1,SOCKET accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);

s:套接字描述符,这个套接字已经设置为监听状态

addr:指向一个缓冲区的指针,用来接收连接实体的地址(客户端连接时,保存这个客户端的Ip地址信息和端口信息)

addrlen:也是返回参数,返回包含地址信息的长度

14.3.7 send函数:向一个已经建立连接的套接字发送数据

1, int send(SOCKET s, const char FAR *buf, int len, int flags);

s:已经建立连接的套接字

buf:指向一个缓冲区,包含将要传递的数据

len:缓冲区的长度

flags:这个值将影响函数的行为,一般设为0

14.3.8 recv函数:从一个已连接的套接字接收数据

1, int recv(SOCKET s, const char FAR *buf, int len, int flags);

s:已经建立连接的套接字

buf:指向一个缓冲区,保存接收的数据

len:缓冲区的长度

flags:这个值将影响函数的行为,一般设为0

14.3.9 connect:与一个特定的套接字建立连接(客户端连接服务器)

Int connect(SOCKET s, const struct socketaddr FAR *name, int namelen);

s:即将在其上就建立连接是那个套接字

name:设定连接的服务器端地址信息

namelen:指定服务器端地址长度

14.3.10 recvfrom:接收一个数据报信息并保存源地址

1,int recvfrom(

SOCKET s,  // 准备接收数据的套接字

char FAR* buf,  // 指向一个缓冲区的指针,用来接收数据

int len, // 缓冲区的长度

int flags, // 与send函数的第四个参数类似

struct sockaddr FAR* from,  // 接收发送数据方的地址信息

int FAR* fromlen // 输入输出参数,函数调用之后,会通过这个参数返回一个值,该返回值是地址结构的大小

);

14.3.11 sendto:向一个特定的目的方发送数据

1,int sendto(

SOCKET s,  // 一个套接字描述符(可能已经建立连接)

char FAR* buf,  // 指向一个缓冲区的指针,包含将要发送的数据

int len, // 缓冲区的长度

int flags, // 与send函数的第四个参数类似

struct sockaddr FAR* to,  // 可选的指针,指定目标套接字的地址

int FAR* tolen // 参数to中指定的地址的长度

);

14.3.12 htons和htonl函数

1,u_shorts htons(u_short hostshort); // 把一个u_short类型的值从主机字节顺序转换成TCP/IP网络字节顺序

参数:一个以主机字节顺序表示的16位数值

2,u_long htonl(u_long hostshort); // 把一个u_long类型的值从主机字节顺序转换成TCP/IP网络字节顺序

参数:一个以主机字节顺序表示的32位数值

注意:当链接不到这个库的时候,可以这样进行显示加载(这个是我测试时遇到的问题)

#include<Winsock2.h>

// 显示加载这个库WS2_32.DLL

#pragma comment(lib, "WS2_32");

下面这张图很早以前找的,已经忘了原出处了,我觉得可以加深我们对网络编程的理解,就搬过来了。

如果有人知道原出处在哪麻烦告知一下。 

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-12-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据传输服务
腾讯云数据传输服务(Data Transfer Service,DTS)可帮助用户在业务不停服的前提下轻松完成数据库迁移上云,利用实时同步通道轻松构建高可用的数据库多活架构,通过数据订阅来满足商业数据挖掘、业务异步解耦等场景需求。同时,DTS 还提供私有化独立输出版本 DTS-DBbridge,支持异构数据库和同构数据库之间迁移和同步,可以帮助企业实现完整数据库迁移(如 Oracle)。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档