网络编程的原理(网络编程的本质)

http://www.itjxue.com  2023-02-04 11:53  来源:未知  点击次数: 

网络编程具体是学什么内容的

是从网络通信的编程原理和开发基础入手,阐述主机扫描、TCP协议编程、UDP协议编程、远程屏幕监视、木马程序、IP语音网络编程、E-mail协议编程、FTP协议编程、网络信息加密传输和网络信息隐藏通信编程等原理、技术和实现方法。每章都有丰富的程序源代码和实验项目。《普通高等学校应用性人才培养系列规划教材:计算机网络编程技术》以套接字编程为基本路线,力求体现网络编程的技术陛、实用性和安全性,在IP语音网络通信和网络信息隐藏通信等章节,还综合体现了科研成果和技术开发的相关应用,具有一定的先进性。《普通高等学校应用性人才培养系列规划教材:计算机网络编程技术》适合作为高等院校计算机及相关专业学生的教材,也可作为多媒体网络通信和安全编程人员的参考书

网络编程的select()函数工作原理

Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是

习惯写诸如connect、

accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或

是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返

回)。可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要

等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相

同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程

序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。下面详细介绍一下!

Select的函数格式(我所说的是Unix系统下的伯克利socket编程,和windows下的有区别,一会儿说明):

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set

*errorfds,struct timeval *timeout);

先说明两个结构体:

第一,struct

fd_set可以理解为一个集合,这个集合中存放的是文件描述符(file descriptor),即文件句

柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,

所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符。fd_set集合可以通过一些宏由人为来

操作,比如清空集合 FD_ZERO(fd_set *),将一个给定的文件描述符加入集合之中FD_SET(int ,fd_set

*),将

一个给定的文件描述符从集合中删除FD_CLR(int

,fd_set*),检查集合中指定的文件描述符是否可以读写FD_ISSET(int ,fd_set* )。一会儿举例说明。

第二,struct

timeval是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个是毫秒

数。具体解释select的参数:

int

maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!

在Windows中这个参数的值无所谓,可以设置不正确。

fd_set

*readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述

符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返

回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出

timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。

fd_set

*writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述

符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返

回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出

timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。

fd_set *errorfds同上面两个参数的意图,用来监视文件错误异常。

struct

timeval* timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第

一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某

个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符

是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就

是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎

样一定返回,返回值同上述。

返回值:

负值:select错误 正值:某些文件可读写或出错 0:等待超时,没有可读写或错误的文件

在有了select后可以写出像样的网络程序来!举个简单的例子,就是从网络上接受数据写入一个文件中。

例子:

main()

{

int

sock;

FILE

*fp;

struct

fd_set fds;

struct

timeval timeout={3,0}; //select等待3秒,3秒轮询,要非阻塞就置0

char

buffer[256]={0}; //256字节的接收缓冲区

while(1)

{

FD_ZERO(fds); //每次循环都要清空集合,否则不能检测描述符变化

FD_SET(sock,fds); //添加描述符

FD_SET(fp,fds); //同上

maxfdp=sockfp?sock+1:fp+1; //描述符最大值加1

switch(select(maxfdp,fds,fds,NULL,timeout))

//select使用

{

case -1: exit(-1);break; //select错误,退出程序

case 0:break; //再次轮询

default:

if(FD_ISSET(sock,fds)) //测试sock是否可读,即是否网络上有数据

{

recvfrom(sock,buffer,256,.....);//接受网络数据

if(FD_ISSET(fp,fds)) //测试文件是否可写

fwrite(fp,buffer...);//写入文件

buffer清空;

}// end if break;

}// end switch

}//end

while

}//end main

如何学习网络编程

具体到编程,用java来实现网络编程是很容易的,可以作为网络编程的入门。使用C++和winsock相对复杂一些。总之看实际需要了。 你好初学网络编程者可以从以下几个步骤开展:1)下载一个可以互动的学习工具,通过这个与这个工具互动,我们可以及时的学到每个api的结果如果。我个人强烈推荐一个互动好工具,即python,下载地址

对于有c/c++或java基础的朋友通过一两个礼拜的时间就可以上手了,另外个人建议初学者可以学习dive into python。2)掌握网络编程中会用到的几个基本概念和内涵,比如IP地址,port号,socket等3)记住和消化网络编程C/S模型,把server和client端编程的常用模式理解和消化4)花几天时间学习socket api集,api集可以分为下面几大类:创建 socket bind listen accept收发 read/recv/recvfrom write/send/sendto关闭 close shutdown参数 getsockopt/setsockopt地址 gethostbyaddr getaddrbyhost,...在学习这些api时候,可以先关注在函数功能,参数意义上5)结合python互动平台,实践socket api的用法,比如socket函数怎么使用,bind怎么使用等等。在互动过程中,我们可以变换参数,看看调用结果如何。比如,创建一个tcp socket的语法如下:socket(AF_INET,SOCK_STREAM)创建一个udp socket的语法如下:socket(AF_INET,SOCK_DGRAM)6)学习socket server端编程实现简单规约比如echo,time等,然后通过cmd中的telnet来测试。7)学习I/O模型,比如阻塞、非阻塞和反应式(select,poll,WaitForMultipleObject)等8)学习Richard Stevens的《Unix网络编程》,深入学习其中的api原理以及服务端设计原理,并通过代码编写。9)下载高性能网络编程框架twisted,笔者强烈推荐,它将使你的网络编程效率提高10倍以上。10)学习设计模式、操作系统知识比如线程、进程、同步等。邻家阿呆 回答采纳率:29.0% 2008-12-18 09:55检举我是高手,我可以教你1.明确学习目的学习编程对大多数IT业人员来说都是非常有用的。学编程,做一名编程人员,从个人角度讲,可以解决在软件使用中所遇到的问题,改进现有软件,可以为自己找到一份理想的工作添加重要得砝码,有利于在求职道路上谋得一个好的职位;从国家的角度,可以为中国的软件产业做出应有的贡献,一名优秀的程序员永远是被争夺的对象。学习编程还能 锻炼思维,使我们的逻辑思维更加严密;能够不断享受到创新的乐趣,将一直有机会走在高科技的前沿,因为程序设计本身是一种创造性的工作。知识经济时代给我们带来了无限的机会,要想真正掌握计算机技术,并在IT行业里干出一番事业来,有所作为,具有一定的编程能力是一个基本条件和要求。2.打好基础学编程要具备一定的基础,总结之有以下几方面:(1)数学基础 从计算机发展和应用的历史来看计算机的数学模型和体系结构等都是有数学家提出的,最早的计算机也是为数值计算而设计的。因此,要学好计算机就要有一定的数学基础,出学者有高中水平就差不多了。(2)逻辑思维能力的培养 学程序设计要有一定的逻辑思维能力,“逻思力”的培养要长时间的实践锻炼。要想成为一名优秀的程序员,最重要的是掌握编程思想。要做到这一点必须在反复的实践、观察、分析、比较、总结中逐渐地积累。因此在学习编程过程中,我们不必等到什么都完全明白了才去动手实践,只要明白了大概,就要敢于自己动手去体验。谁都有第一次。有些问题只有通过实践后才能明白,也只有实践才能把老师和书上的知识变成自己的,高手都是这样成材的。

想要网络编程,应该要学习什么?

1、基本原理:《计算机网络——自顶向下方法》了解整个网络系统构建的概貌

2、程序层面:《Unix网络编程》 了解网路在程序层面的接口

3、后台:了解数据库《数据库系统概念》不错耶鲁大学那本哈

4、后台:了解java或者php之一,学会apache配置

5、详细了解前端技术

网络编程(五)TCP详解

考虑最简单的情况:两台主机之间的通信。这个时候只需要一条网线把两者连起来,规定好彼此的硬件接口,如都用 USB、电压 10v、频率 2.4GHz 等, 这一层就是物理层,这些规定就是物理层协议 。

我们当然不满足于只有两台电脑连接,因此我们可以使用交换机把多个电脑连接起来,如下图:

这样连接起来的网络,称为局域网,也可以称为以太网(以太网是局域网的一种)。在这个网络中,我们需要标识每个机器,这样才可以指定要和哪个机器通信。这个标识就是硬件地址 MAC。

硬件地址随机器的生产就被确定,永久性唯一。在局域网中,我们需要和另外的机器通信时,只需要知道他的硬件地址,交换机就会把我们的消息发送到对应的机器。

这里我们可以不管底层的网线接口如何发送,把物理层抽离,在他之上创建一个新的层次,这就是 数据链路层 。

我们依然不满足于局域网的规模,需要把所有的局域网联系起来,这个时候就需要用到路由器来连接两个局域网:

但是如果我们还是使用硬件地址来作为通信对象的唯一标识,那么当网络规模越来越大,需要记住所有机器的硬件地址是不现实的;

同时,一个网络对象可能会频繁更换设备,这个时候硬件地址表维护起来更加复杂。这里使用了一个新的地址来标记一个网络对象: IP 地址 。

通过一个简单的寄信例子来理解 IP 地址。

我住在北京市,我朋友 A 住在上海市,我要给朋友 A 写信:

因此,这里 IP 地址就是一个网络接入地址(朋友 A 的住址),我只需要知道目标 IP 地址,路由器就可以把消息给我带到。 在局域网中,就可以动态维护一个 MAC 地址与 IP 地址的映射关系,根据目的 IP 地址就可以寻找到机器的 MAC 地址进行发送 。

这样我们不需管理底层如何去选择机器,我们只需要知道 IP 地址,就可以和我们的目标进行通信。这一层就是 网络层 。网络层的核心作用就是 提供主机之间的逻辑通信 。

这样,在网络中的所有主机,在逻辑上都连接起来了,上层只需要提供目标 IP 地址和数据,网络层就可以把消息发送到对应的主机。

一个主机有多个进程,进程之间进行不同的网络通信,如边和朋友开黑边和女朋友聊微信。我的手机同时和两个不同机器进行通信。

那么当我的手机收到数据时,如何区分是微信的数据,还是王者的数据?那么就必须在网络层之上再添加一层: 运输层 :

运输层通过 socket(套接字),将网络信息进行进一步的拆分,不同的应用进程可以独立进行网络请求,互不干扰。

这就是运输层的最本质特点: 提供进程之间的逻辑通信 。这里的进程可以是主机之间,也可以是同个主机,所以在 android 中,socket 通信也是进程通信的一种方式。

现在不同的机器上的应用进程之间可以独立通信了,那么我们就可以在计算机网络上开发出形形式式的应用:如 web 网页的 http,文件传输 ftp 等等。这一层称为 应用层 。

应用层还可以进一步拆分出表示层、会话层,但他们的本质特点都没有改变: 完成具体的业务需求 。和下面的四层相比,他们并不是必须的,可以归属到应用层中。

最后对计网分层进行小结:

这里需要注意的是,分层并不是在物理上的分层,而是逻辑上的分层。通过对底层逻辑的封装,使得上层的开发可以直接依赖底层的功能而无需理会具体的实现,简便了开发。

这种分层的思路,也就是责任链设计模式,通过层层封装,把不同的职责独立起来,更加方便开发、维护等等。

TCP 并不是把应用层传输过来的数据直接加上首部然后发送给目标,而是把数据看成一个字节 流,给他们标上序号之后分部分发送。这就是 TCP 的 面向字节流 特性:

面向字节流的好处是无需一次存储过大的数据占用太多内存,坏处是无法知道这些字节代表的意义,例如应用层发送一个音频文件和一个文本文件,对于 TCP 来说就是一串字节流,没有意义可言,这会导致粘包以及拆包问题,后面讲。

前面讲到,TCP 是可靠传输协议,也就是,一个数据交给他,他肯定可以完整无误地发送到目标地址,除非网络炸了。他实现的网络模型如下:

对于应用层来说,他就是一个可靠传输的底层支持服务;而运输层底层采用了网络层的不可靠传输。虽然在网络层甚至数据链路层就可以使用协议来保证数据传输的可靠性,但这样网络的设计会更加复杂、效率会随之降低。把数据传输的可靠性保证放在运输层,会更加合适。

可靠传输原理的重点总结一下有: 滑动窗口、超时重传、累积确认、选择确认、连续 ARQ 。

停止等待协议

要实现可靠传输,最简便的方法就是:我发送一个数据包给你,然后你跟我回复收到,我继续发送下一个数据包。传输模型如下:

这种“一来一去”的方法来保证传输可靠就是 停止等待协议 (stop-and-wait)。不知道还记不记得前面 TCP 首部有一个 ack 字段,当他设置为 1 的时候,表示这个报文是一个确认收到报文。

然后再来考虑另一种情况:丢包。网络环境不可靠,导致每一次发送的数据包可能会丢失,如果机器 A 发送了数据包丢失了,那么机器 B 永远接收不到数据,机器 A 永远在等待。

解决这个问题的方法是: 超时重传 。当机器 A 发出一个数据包时便开始计时,时间到还没收到确认回复,就可以认为是发生了丢包,便再次发送,也就是重传。

但重传会导致另一种问题:如果原先的数据包并没有丢失,只是在网络中待的时间比较久,这个时候机器 B 会受到两个数据包,那么机器 B 是如何辨别这两个数据包是属于同一份数据还是不同的数据?

这就需要前面讲过的方法: 给数据字节进行编号 。这样接收方就可以根据数据的字节编号,得出这些数据是接下来的数据,还是重传的数据。

在 TCP 首部有两个字段:序号和确认号,他们表示发送方数据第一个字节的编号,和接收方期待的下一份数据的第一个字节的编号。

停止等待协议的优点是简单,但缺点是 信道利用率 太低。

假定AB之间有一条直通的信道来传送分组

这里的TD是A发送分组所需要的时间(显然TD = 分组长度 / 数据速率)再假定TA是B发送确认分组所需要的时间(A和B处理分组的时间都忽略不计)那么A在经过TD+RTT+TA时间后才能发送下一个分组,这里的RTT是往返时间,因为只有TD是采用来传输有用的数据(这个数据包括了分组首部,如果可以知道传输更精确的数据的时间,可以计算的更精确),所有信道利用率为

为了提高传输效率,发送方可以不使用低效率的停止等待协议,而是采用 流水线传输 :就是发送方可以 连续的发送多个分组 ,不必每发完一个分组就停下来等待对方的确认。这样可使信道上一直有数据不间断地在传送。显然这种传输方式可以获得很高的信道利用率

停止等待协议已经可以满足可靠传输了,但有一个致命缺点: 效率太低 。发送方发送一个数据包之后便进入等待,这个期间并没有干任何事,浪费了资源。解决的方法是: 连续发送数据包 。

也就是下面介绍的 连续ARQ协议 和 滑动窗口协议

连续 ARQ 协议

模型如下:

和停止等待最大的不同就是,他会源源不断地发送,接收方源源不断收到数据之后,逐一进行确认回复。这样便极大地提高了效率。但同样,带来了一些额外的问题:

发送是否可以无限发送直到把缓冲区所有数据发送完?不可以。因为需要考虑接收方缓冲区以及读取数据的能力。如果发送太快导致接收方无法接受,那么只是会频繁进行重传,浪费了网络资源。所以发送方发送数据的范围,需要考虑到接收方缓冲区的情况。这就是 TCP 的 流量控制 。

解决方法是: 滑动窗口 。基本模型如下:

在 TCP 的首部有一个窗口大小字段,他表示接收方的剩余缓冲区大小,让发送方可以调整自己的发送窗口大小。通过滑动窗口,就可以实现 TCP 的流量控制,不至于发送太快,导致太多的数据丢失。

连续 ARQ 带来的第二个问题是:网络中充斥着和发送数据包一样数据量的确认回复报文,因为每一个发送数据包,必须得有一个确认回复。提高网络效率的方法是: 累积确认 。

接收方不需要逐个进行回复,而是累积到一定量的数据包之后,告诉发送方,在此数据包之前的数据全都收到。例如,收到 1234,接收方只需要告诉发送方我收到 4 了,那么发送方就知道 1234 都收到了。

第三个问题是:如何处理丢包情况。在停止等待协议中很简单,直接一个超时重传就解决了。但,连续 ARQ 中不太一样。

例如:接收方收到了 123 567,六个字节,编号为 4 的字节丢失了。按照累积确认的思路,只能发送 3 的确认回复,567 都必须丢掉,因为发送方会进行重传。这就是 GBN(go-back-n) 思路。

但是我们会发现,只需要重传 4 即可,这样不是很浪费资源,所以就有了: 选择确认 SACK 。在 TCP 报文的选项字段,可以设置已经收到的报文段,每一个报文段需要两个边界来进行确定。这样发送方,就可以根据这个选项字段只重传丢失的数据了。

第四个问题是:拥塞控制的问题

也是通过窗口的大小来控制的,但是检测网络满不满是个挺难的事情,所以 TCP 发送包经常被比喻成往谁管理灌水,所以拥塞控制就是在不堵塞,不丢包的情况下尽可能的发挥带宽。

水管有粗细,网络有带宽,即每秒钟能发送多少数据;水管有长度,端到端有时延。理想状态下,水管里面的水 = 水管粗细 * 水管长度。对于网络上,通道的容量 = 带宽 * 往返时延。

如果我们设置发送窗口,使得发送但未确认的包为通道的容量,就能撑满整个管道。

如图所示,假设往返时间为 8 秒,去 4 秒,回 4 秒,每秒发送一个包,已经过去了 8 秒,则 8 个包都发出去了,其中前四个已经到达接收端,但是 ACK 还没返回,不能算发送成功,5-8 后四个包还在路上,还没被接收,这个时候,管道正好撑满,在发送端,已发送未确认的 8 个包,正好等于带宽,也即每秒发送一个包,也即每秒发送一个包,乘以来回时间 8 秒。

如果在这个基础上调大窗口,使得单位时间可以发送更多的包,那么会出现接收端处理不过来,多出来的包会被丢弃,这个时候,我们可以增加一个缓存,但是缓存里面的包 4 秒内肯定达不到接收端课,它的缺点会增加时延,如果时延达到一定程度就会超时重传

TCP 拥塞控制主要来避免两种现象,包丢失和超时重传,一旦出现了这些现象说明发送的太快了,要慢一点。

具体的方法就是发送端慢启动,比如倒水,刚开始倒的很慢,渐渐变快。然后设置一个阈值,当超过这个值的时候就要慢下来

慢下来还是在增长,这时候就可能水满则溢,出现拥塞,需要降低倒水的速度,等水慢慢渗下去。

拥塞的一种表现是丢包,需要超时重传,这个时候,采用快速重传算法,将当前速度变为一半。所以速度还是在比较高的值,也没有一夜回到解放前。

到这里关于 TCP 的可靠传输原理就已经介绍得差不多。最后进行一个小结:

当然,这只是可靠传输的冰山一角,感兴趣可以再深入去研究

什么是网络编程啊?

网络编程的主要对象就是浏览器 因为我们上网基本上是依赖浏览器的,当然,像游戏,聊天软件等等这些不依赖浏览器,但需要网络协议,不同的协议,有不同的共能,网络编程就是做这些,浏览器:一大堆接口给你摆这了,想做成什么样?自己实现去吧。网络协议:这个跟前面的差不多也有一些接口,或者服务条款等等(嘿嘿,还没研究那么深)然后还是要我们编程人员来实现,我们可以从以上信息中得到它们运行的机制,特点,模式,语言,服务规定等等信息,熟知这些后,我们就可以编程了,利用它自身的东西,在加上我们需要而且符合它规范,且可运行的东西,就是编出来的东西啦~这个就是网络编程啦~HOHO

(责任编辑:IT教学网)

更多

推荐SQL Server文章