网络编程

 

课程介绍
1. 网络概述、udp
1.1. 网络通信概述
1.2. tcp/ip简介
1.3. 端口
1.4. ip地址
1.5. 子网掩码
1.6. socket简介
1.7. udp介绍
1.8. udp网络程序-发送数据
1.9. udp网络程序-发送、接收数据
1.10. udp网络程序-端口问题
1.11. udp绑定信息
1.12. udp网络通信过程
1.13. udp应用:echo服务器
1.14. udp应用:聊天室
1.15. udp总结
1.16. udp综合作业-模拟QQ
2. TFTP项目、TCP编程
2.1. wireshark抓包工具使用
2.2. TFTP下载演示
2.3. 应用:TFTP客户端
2.4. udp广播
2.5. tcp相关介绍
2.6. tcp服务器
2.7. tcp客户端
2.8. 应用:模拟QQ聊天
3. 网络通信过程详解
3.1. Packet Tracer网络通信过程
3.2. 2台电脑组网
3.3. 通过集线器组网
3.4. 通过交换机组网
3.5. 通过路由器组网
3.6. 交换机、路由器、服务器组网
3.7. tcp三次挥手
3.8. tcp四次挥手
3.9. tcp十种状态
3.10. tcp的2MSL问题
3.11. tcp长连接和短连接
3.12. listen的队列长度
3.13. 手动配置ip
3.14. 常见网络攻击案例
3.15. 家庭上网解析
4. 并发服务器、HTTP协议
4.1. 单进程服务器
4.2. 多进程服务器
4.3. 多线程服务器
4.4. 单进程服务器-非堵塞模式
4.5. 单进程服务器-select版
4.6. 单进程服务器-epoll版
4.7. 多任务实现-协程
4.8. 协程-greenlet版
4.9. 协程-gevent版
4.10. 单进程服务器-gevent版

 

 

 

课程介绍


1. 网络概述、udp

今日知识点

  1. tcp/ip协议介绍
  2. ip地址的分类
  3. 端口、端口号
  4. (重点)socket
  5. (重点)udp通信
  6. (重点、难点)udp应用-echo服务器、聊天室、多线程模拟QQ聊天


1.1. 网络通信概述

网络通信概述

1. 什么是网络

说明

  • 网络就是一种辅助双方或者多方能够连接在一起的工具
  • 如果没有网络可想单机的世界是多么的孤单

单机游戏(不能和远在他乡的朋友一起玩)

2. 使用网络的目的

就是为了联通多方然后进行通信用的,即把数据从一方传递给另外一方

前面的学习编写的程序都是单机的,即不能和其他电脑上的程序进行通信

为了让在不同的电脑上运行的软件,之间能够互相传递数据,就需要借助网络的功能

小总结

  • 使用网络能够把多方链接在一起,然后可以进行数据传递
  • 所谓的网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信

 


1.2. tcp/ip简介

tcp/ip简介

作为新时代标杆的我们,已经离不开手机、离不开网络,对于互联网大家可能耳熟能详,但是计算机网络的出现比互联网要早很多

1. 什么是协议

 

有的说英语,有的说中文,有的说德语,说同一种语言的人可以交流,不同的语言之间就不行了

为了解决不同种族人之间的语言沟通障碍,现规定国际通用语言是英语,这就是一个规定,这就是协议

2. 计算机网络沟通用什么

现在的生活中,不同的计算机只需要能够联网(有线无线都可以)那么就可以相互进行传递数据

 

那么不同种类之间的计算机到底是怎么进行数据传递的呢?

就像说不同语言的人沟通一样,只要有一种大家都认可都遵守的协议即可,那么这个计算机都遵守的网络通信协议叫做TCP/IP协议

3. TCP/IP协议(族)

早期的计算机网络,都是由各厂商自己规定一套协议,IBM、Apple和Microsoft都有各自的网络协议,互不兼容

为了把全世界的所有不同类型的计算机都连接起来,就必须规定一套全球通用的协议,为了实现互联网这个目标,互联网协议簇(Internet Protocol Suite)就是通用协议标准。

因为互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP协议,所以,大家把互联网的协议简称TCP/IP协议

常用的网络协议如下图所示:

 

说明:

网际层也称为:网络层
网络接口层也称为:链路层


1.3. 端口

端口

1. 什么是端口

那么TCP/IP协议中的端口指的是什么呢?

端口就好一个房子的门,是出入这间房子的必经之路。

如果一个进程需要收发网络数据,那么就需要有这样的端口

在linux系统中,端口可以有65536(2的16次方)个之多!

既然有这么多,操作系统为了统一管理,所以进行了编号,这就是端口号

2. 端口号

端口是通过端口号来标记的,端口号只有整数,范围是从0到65535

3. 端口是怎样分配的

端口号不是随意使用的,而是按照一定的规定进行分配。

端口的分类标准有好几种,我们这里不做详细讲解,只介绍一下知名端口和动态端口

3.1 知名端口(Well Known Ports)

知名端口是众所周知的端口号,范围从0到1023

80端口分配给HTTP服务
21端口分配给FTP服务

可以理解为,一些常用的功能使用的号码是估计的,好比 电话号码110、10086、10010一样

一般情况下,如果一个程序需要使用知名端口的需要有root权限

3.2 动态端口(Dynamic Ports)

动态端口的范围是从1024到65535

之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。

动态分配是指当一个系统进程或应用程序进程需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用。

当这个进程关闭时,同时也就释放了所占用的端口号。

3.3 怎样查看端口 ?

用“netstat -an”查看端口状态

4. 小总结

端口有什么用呢 ? 我们知道,一台拥有IP地址的主机可以提供许多服务,比如HTTP(万维网服务)、FTP(文件传输)、SMTP(电子邮件)等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。 需要注意的是,端口并不是一一对应的。比如你的电脑作为客户机访问一台WWW服务器时,WWW服务器使用“80”端口与你的电脑通信,但你的电脑则可能使用“3457”这样的端口。


1.4. ip地址

ip地址

1. 什么是地址

地址就是用来标记地点的

2. ip地址的作用

ip地址:用来在网络中标记一台电脑的一串数字,比如192.168.1.1;在本地局域网上是惟一的。

 

3.1 A类IP地址

一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”,

地址范围1.0.0.1-126.255.255.254

二进制表示为:00000001 00000000 00000000 00000001 - 01111110 11111111 11111111 11111110

可用的A类网络有126个,每个网络能容纳1677214个主机

3.2 B类IP地址

一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”,

地址范围128.1.0.1-191.255.255.254

二进制表示为:10000000 00000001 00000000 00000001 - 10111111 11111111 11111111 11111110

可用的B类网络有16384个,每个网络能容纳65534主机

3.3 C类IP地址

一个C类IP地址由3字节的网络地址和1字节的主机地址组成,网络地址的最高位必须是“110”

范围192.0.1.1-223.255.255.254

二进制表示为: 11000000 00000000 00000001 00000001 - 11011111 11111111 11111110 11111110

C类网络可达2097152个,每个网络能容纳254个主机

3.4 D类地址用于多点广播

D类IP地址第一个字节以“1110”开始,它是一个专门保留的地址。

它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中

多点广播地址用来一次寻址一组计算机

地址范围224.0.0.1-239.255.255.254

3.5 E类IP地址

以“1111”开始,为将来使用保留

E类地址保留,仅作实验和开发用

3.6 私有ip

在这么多网络IP中,国际规定有一部分IP地址是用于我们的局域网使用,也就

是属于私网IP,不在公网中使用的,它们的范围是:

10.0.0.0~10.255.255.255

172.16.0.0~172.31.255.255

192.168.0.0~192.168.255.255

3.7 注意

IP地址127.0.0.1~127.255.255.255用于回路测试,

如:127.0.0.1可以代表本机IP地址,用http://127.0.0.1就可以测试本机中配置的Web服务器。

3. ip地址的分类

每一个IP地址包括两部分:网络地址和主机地址


1.5. 子网掩码

子网掩码

要想理解什么是子网掩码,就不能不了解IP地址的构成。互联网是由许多小型网络构成的,每个网络上都有许多主机,这样便构成了一个有层次的结构。IP地址在设计时就考虑到地址分配的层次特点,将每个IP地址都分割成网络号和主机号两部分,以便于IP地址的寻址操作。

IP地址的网络号和主机号各是多少位呢?

如果不指定,就不知道哪些位是网络号、哪些是主机号,这就需要通过子网掩码来实现。

子网掩码不能单独存在,它必须结合IP地址一起使用。

子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分子网掩码的设定必须遵循一定的规则。

与IP地址相同,子网掩码的长度也是32位,

  • 左边是网络位,用二进制数字“1”表示;
  • 右边是主机位,用二进制数字“0”表示。

假设IP地址为“192.168.1.1”子网掩码为“255.255.255.0”。

其中,“1”有24个,代表与此相对应的IP地址左边24位是网络号;

“0”有8个,代表与此相对应的IP地址右边8位是主机号。

这样,子网掩码就确定了一个IP地址的32位二进制数字中哪些是网络号、哪些是主机号。

这对于采用TCP/IP协议的网络来说非常重要,只有通过子网掩码,才能表明一台主机所在的子网与其他子网的关系,使网络正常工作。

最常用的两种子网掩码

子网掩码是“255.255.255.0”的网络:

最后面一个数字可以在0~255范围内任意变化,因此可以提供256个IP地址。
但是实际可用的IP地址数量是256-2,即254个,因为主机号不能全是“0”或全是“1”。

主机号全为0,表示网络号

主机号全为1,表示网络广播

注意

如果将子网掩码设置过大,也就是说子网范围扩大,那么,根据子网寻径规则,很可能发往和本地主机不在同一子网内的目标主机的数据,会因为错误的判断而认为目标主机是在同一子网内,那么,数据包将在本子网内循环,直到超时并抛弃,使数据不能正确到达目标主机,导致网络传输错误;如果将子网掩码设置得过小,那么就会将本来属于同一子网内的机器之间的通信当做是跨子网传输,数据包都交给缺省网关处理,这样势必增加缺省网关(文章下方有解释)的负担,造成网络效率下降。因此,子网掩码应该根据网络的规模进行设置。如果一个网络的规模不超过254台电脑,采用“255.255.255.0”作为子网掩码就可以了,现在大多数局域网都不会超过这个数字,因此“255.255.255.0”是最常用的IP地址子网掩码;假如在一所大学具有1500多台电脑,这种规模的局域网可以使用“255.255.0.0”。


1.6. socket简介

socket简介

1.本地的进程间通信(IPC)有很多种方式,例如

  • 队列
  • 同步(互斥锁、条件变量等)

以上通信方式都是在一台机器上不同进程之间的通信方式,那么问题来了

网络中进程之间如何通信?

2. 网络中进程之间如何通信

首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!

在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。

其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。

这样利用ip地址,协议,端口就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互

3. 什么是socket

socket(简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:

它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的

例如我们每天浏览网页、QQ 聊天、收发 email 等等

4. 创建socket

在 Python 中 使用socket 模块的函数 socket 就可以完成:

socket.socket(AddressFamily, Type)

说明:

函数 socket.socket 创建一个 socket,返回该 socket 的描述符,该函数带有两个参数:

  • Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
  • Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)

创建一个tcp socket(tcp套接字)

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print 'Socket Created'

创建一个udp socket(udp套接字)

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

print 'Socket Created'


1.7. udp介绍

UDP介绍

UDP --- 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

UDP是一种面向无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

UDP特点:

UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。 UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内。 UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。

【适用情况】

UDP是面向消息的协议,通信时不需要建立连接,数据的传输自然是不可靠的,UDP一般用于多点通信和实时的数据业务,比如

  • 语音广播
  • 视频
  • QQ
  • TFTP(简单文件传送)
  • SNMP(简单网络管理协议)
  • RIP(路由信息协议,如报告股票市场,航空信息)
  • DNS(域名解释)

注重速度流畅

UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。


1.8. udp网络程序-发送数据

udp网络程序-发送数据

创建一个udp客户端程序的流程是简单,具体步骤如下:

  1. 创建客户端套接字
  2. 发送/接收数据
  3. 关闭套接字

代码如下:

#coding=utf-8

from socket import *

#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 准备接收方的地址
sendAddr = ('192.168.1.103', 8080)

#3. 从键盘获取数据
sendData = raw_input("请输入要发送的数据:")

#4. 发送数据到指定的电脑上
udpSocket.sendto(sendData, sendAddr)

#5. 关闭套接字
udpSocket.close()

运行现象:

在Ubuntu中运行脚本:

在windows中运行“网络调试助手”:

 


1.9. udp网络程序-发送、接收数据

udp网络程序-发送、接收数据

1. 创建udp网络程序-接收数据

#coding=utf-8

from socket import *

#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 准备接收方的地址
sendAddr = ('192.168.1.103', 8080)

#3. 从键盘获取数据
sendData = raw_input("请输入要发送的数据:")

#4. 发送数据到指定的电脑上
udpSocket.sendto(sendData, sendAddr)

#5. 等待接收对方发送的数据
recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

#6. 显示对方发送的数据
print(recvData)

#7. 关闭套接字
udpSocket.close()

python脚本:

 

网络调试助手截图:

 


1.10. udp网络程序-端口问题

udp网络程序-端口问题

会变的端口号

重新运行多次脚本,然后在“网络调试助手”中,看到的现象如下:

 

说明:

  • 每重新运行一次网络程序,上图中红圈中的数字,不一样的原因在于,这个数字标识这个网络程序,当重新运行时,如果没有确定到底用哪个,系统默认会随机分配
  • 记住一点:这个网络程序在运行的过程中,这个就唯一标识这个程序,所以如果其他电脑上的网络程序如果想要向此程序发送数据,那么就需要向这个数字(即端口)标识的程序发送即可


1.11. udp绑定信息

udp绑定信息

1. 绑定信息

还记得在上一节课中,如果一个网络程序在每次运行的时候端口是随机变化的么?

一般情况下,在一天电脑上运行的网络程序有很多,而各自用的端口号很多情况下不知道,为了不与其他的网络程序占用同一个端口号,往往在编程中,udp的端口号一般不绑定

但是如果需要做成一个服务器端的程序的话,是需要绑定的,想想看这又是为什么呢?

如果报警电话每天都在变,想必世界就会乱了,所以一般服务性的程序,往往需要一个固定的端口号,这就是所谓的端口绑定

 

2. 绑定示例

#coding=utf-8

from socket import *

#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 绑定本地的相关信息,如果一个网络程序不绑定,则系统会随机分配
bindAddr = ('', 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddr)

#3. 等待接收对方发送的数据
recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

#4. 显示接收到的数据
print recvData

#5. 关闭套接字
udpSocket.close()

运行结果:

测试端

 

本程序

 

3. 总结

  • 一个udp网络程序,可以不绑定,此时操作系统会随机进行分配一个端口,如果重新运行次程序端口可能会发生变化
  • 一个udp网络程序,也可以绑定信息(ip地址,端口号),如果绑定成功,那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的


1.12. udp网络通信过程

 


1.13. udp应用:echo服务器

udp应用:echo服务器

1. 运行现象

测试端

 

 

echo服务器端

 

 

2. 参考代码

#coding=utf-8

from socket import *

#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 绑定本地的相关信息
bindAddr = ('', 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddr)

num = 1
while True:

    #3. 等待接收对方发送的数据
    recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

    #4. 将接收到的数据再发送给对方
    udpSocket.sendto(recvData[0], recvData[1])

    #5. 统计信息
    print('已经将接收到的第%d个数据返回给对方,内容为:%s'%(num,recvData[0]))
    num+=1


#5. 关闭套接字
udpSocket.close()


1.14. udp应用:聊天室

udp应用:聊天室

1. 运行现象

测试端

 

聊天室端

 

2. 参考代码

#coding=utf-8

from socket import *
from time import ctime

#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 绑定本地的相关信息
bindAddr = ('', 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddr)

while True:

    #3. 等待接收对方发送的数据
    recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

    #4. 打印信息
    print('【%s】%s:%s'%(ctime(),recvData[1][0],recvData[0]))


#5. 关闭套接字
udpSocket.close()


1.15. udp总结

udp总结

1. udp是TCP/IP协议族中的一种协议能够完成不同机器上的程序间的数据通信

2. udp服务器、客户端

  • udp的服务器和客户端的区分:往往是通过请求服务提供服务来进行区分
  • 请求服务的一方称为:客户端
  • 提供服务的一方称为:服务器

3. udp绑定问题

  • 一般情况下,服务器端,需要绑定端口,目的是为了让其他的客户端能够正确发送到此进程
  • 客户端,一般不需要绑定,而是让操作系统随机分配,这样就不会因为需要绑定的端口被占用而导致程序无法运行的情况


1.16. udp综合作业-模拟QQ

udp综合作业-模拟QQ

1. 任务要求:

  • 使用多线程完成一个全双工的QQ聊天程序

2. 运行现象如下

 


2. TFTP项目、TCP编程

 

2.1. wireshark抓包工具使用

wireshark抓包工具使用

1. 安装wireshark

 

 

2. wireshark的使用

 


2.2. TFTP下载演示


2.3. 应用:TFTP客户端

应用:TFTP客户端

1. TFTP协议介绍

TFTP(Trivial File Transfer Protocol,简单文件传输协议)

是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文件传输的协议

特点:

  • 简单
  • 占用资源小
  • 适合传递小文件
  • 适合在局域网进行传递
  • 端口号为69
  • 基于UDP实现

2. TFTP下载过程

TFTP服务器默认监听69号端口

当客户端发送“下载”请求(即读请求)时,需要向服务器的69端口发送

服务器若批准此请求,则使用一个新的、临时的 端口进行数据传输

 

当服务器找到需要现在的文件后,会立刻打开文件,把文件中的数据通过TFTP协议发送给客户端

如果文件的总大小较大(比如3M),那么服务器分多次发送,每次会从文件中读取512个字节的数据发送过来

因为发送的次数有可能会很多,所以为了让客户端对接收到的数据进行排序,所以在服务器发送那512个字节数据的时候,会多发2个字节的数据,用来存放序号,并且放在512个字节数据的前面,序号是从1开始的

因为需要从服务器上下载文件时,文件可能不存在,那么此时服务器就会发送一个错误的信息过来,为了区分服务发送的是文件内容还是错误的提示信息,所以又用了2个字节 来表示这个数据包的功能(称为操作码),并且在序号的前面

操作码功能
1 读请求,即下载
2 写请求,即上传
3 表示数据包,即DATA
4 确认码,即ACK
5 错误

因为udp的数据包不安全,即发送方发送是否成功不能确定,所以TFTP协议中规定,为了让服务器知道客户端已经接收到了刚刚发送的那个数据包,所以当客户端接收到一个数据包的时候需要向服务器进行发送确认信息,即发送收到了,这样的包成为ACK(应答包)

为了标记数据已经发送完毕,所以规定,当客户端接收到的数据小于516(2字节操作码+2个字节的序号+512字节数据)时,就意味着服务器发送完毕了

TFTP数据包的格式如下:

 

2. 参考代码如下:

#coding=utf-8

from socket import *
import struct
import sys

if len(sys.argv) != 2:
    print('-'*30)
    print("tips:")
    print("python xxxx.py 192.168.1.1")
    print('-'*30)
    exit()
else:
    ip = sys.argv[1]

# 创建udp套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)

#构造下载请求数据
cmd_buf = struct.pack("!H8sb5sb",1,"test.jpg",0,"octet",0)

#发送下载文件请求数据到指定服务器
sendAddr = (ip, 69)
udpSocket.sendto(cmd_buf, sendAddr)

p_num = 0

recvFile = ''

while True:
    recvData,recvAddr = udpSocket.recvfrom(1024)

    recvDataLen = len(recvData)

    # print recvAddr # for test

    # print len(recvData) # for test

    cmdTuple = struct.unpack("!HH", recvData[:4])

    # print cmdTuple # for test

    cmd = cmdTuple[0]
    currentPackNum = cmdTuple[1]        

    if cmd == 3: #是否为数据包

        # 如果是第一次接收到数据,那么就创建文件
        if currentPackNum == 1:
            recvFile = open("test.jpg", "a")

        # 包编号是否和上次相等
        if p_num+1 == currentPackNum:
            recvFile.write(recvData[4:]);
            p_num +=1
            print '(%d)次接收到的数据'%(p_num)

            ackBuf = struct.pack("!HH",4,p_num)

            udpSocket.sendto(ackBuf, recvAddr)
        # 如果收到的数据小于516则认为出错
        if recvDataLen<516:
            recvFile.close()
            print '已经成功下载!!!'
            break

    elif cmd == 5: #是否为错误应答
        print "error num:%d"%currentPackNum
        break

udpSocket.close()

运行现象:


2.4. udp广播

udp广播

现实生活中的广播

 

网络编程中的广播

#coding=utf-8

import socket, sys

dest = ('<broadcast>', 7788)

# 创建udp套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 对这个需要发送广播数据的套接字进行修改设置,否则不能发送广播数据
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST,1)

# 以广播的形式发送数据到本网络的所有电脑中
s.sendto("Hi", dest)

print "等待对方回复(按ctrl+c退出)"

while True:
    (buf, address) = s.recvfrom(2048)
    print "Received from %s: %s" % (address, buf)


2.5. tcp相关介绍

tcp相关介绍

udp通信模型

udp通信模型中,在通信开始之前,不需要建立相关的链接,只需要发送数据即可,类似于生活中,"写信""

 

tcp通信模型

udp通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,"打电话""

 


2.6. tcp服务器

tcp服务器

生活中的电话机

如果想让别人能更够打通咱们的电话获取相应服务的话,需要做一下几件事情:

  1. 买个手机
  2. 插上手机卡
  3. 设计手机为正常接听状态(即能够响铃)
  4. 静静的等着别人拨打

tcp服务器

如同上面的电话机过程一样,在程序中,如果想要完成一个tcp服务器的功能,需要的流程如下:

  1. socket创建一个套接字
  2. bind绑定ip和port
  3. listen使套接字变为可以被动链接
  4. accept等待客户端的链接
  5. recv/send接收发送数据

一个很简单的tcp服务器如下:

#coding=utf-8
from socket import *

# 创建socket
tcpSerSocket = socket(AF_INET, SOCK_STREAM)

# 绑定本地信息
address = ('', 7788)
tcpSerSocket.bind(address)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcpSerSocket.listen(5)

# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器
# newSocket用来为这个客户端服务
# tcpSerSocket就可以省下来专门等待其他新客户端的链接
newSocket, clientAddr = tcpSerSocket.accept()

# 接收对方发送过来的数据,最大接收1024个字节
recvData = newSocket.recv(1024)
print '接收到的数据为:',recvData

# 发送一些数据到客户端
newSocket.send("thank you !")

# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
newSocket.close()

# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接
tcpSerSocket.close()

运行流程:

<1>tcp服务器

 

<2>网络调试助手:

 

 


2.7. tcp客户端

tcp客户端

tcp客户端,并不是像之前一个段子:一个顾客去饭馆吃饭,这个顾客要点菜,就问服务员咱们饭店有客户端么,然后这个服务员非常客气的说道:先生 我们饭店不用客户端,我们直接送到您的餐桌上

如果,不学习网络的知识是不是 说不定也会发生那样的笑话 ,哈哈

所谓的服务器端:就是提供服务的一方,而客户端,就是需要被服务的一方

tcp客户端构建流程

tcp的客户端要比服务器端简单很多,如果说服务器端是需要自己买手机、查手机卡、设置铃声、等待别人打电话流程的话,那么客户端就只需要找一个电话亭,拿起电话拨打即可,流程要少很多

示例代码:

#coding=utf-8
from socket import *

# 创建socket
tcpClientSocket = socket(AF_INET, SOCK_STREAM)

# 链接服务器
serAddr = ('192.168.1.102', 7788)
tcpClientSocket.connect(serAddr)

# 提示用户输入数据
sendData = raw_input("请输入要发送的数据:")

tcpClientSocket.send(sendData)

# 接收对方发送过来的数据,最大接收1024个字节
recvData = tcpClientSocket.recv(1024)
print '接收到的数据为:',recvData

# 关闭套接字
tcpClientSocket.close()

运行流程:

<1>tcp客户端

<2>网络调试助手:

 


2.8. 应用:模拟QQ聊天

应用:模拟QQ聊天

客户端参考代码

#coding=utf-8
from socket import *

# 创建socket
tcpClientSocket = socket(AF_INET, SOCK_STREAM)

# 链接服务器
serAddr = ('192.168.1.102', 7788)
tcpClientSocket.connect(serAddr)

while True:

    # 提示用户输入数据
    sendData = raw_input("send:")

    if len(sendData)>0:
        tcpClientSocket.send(sendData)
    else:
        break

    # 接收对方发送过来的数据,最大接收1024个字节
    recvData = tcpClientSocket.recv(1024)
    print 'recv:',recvData

# 关闭套接字
tcpClientSocket.close()

服务器端参考代码

#coding=utf-8
from socket import *

# 创建socket
tcpSerSocket = socket(AF_INET, SOCK_STREAM)

# 绑定本地信息
address = ('', 7788)
tcpSerSocket.bind(address)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcpSerSocket.listen(5)

while True:

    # 如果有新的客户端来链接服务器,那么就产生一个信心的套接字专门为这个客户端服务器
    # newSocket用来为这个客户端服务
    # tcpSerSocket就可以省下来专门等待其他新客户端的链接
    newSocket, clientAddr = tcpSerSocket.accept()

    while True:

        # 接收对方发送过来的数据,最大接收1024个字节
        recvData = newSocket.recv(1024)

        # 如果接收的数据的长度为0,则意味着客户端关闭了链接
        if len(recvData)>0:
            print 'recv:',recvData
        else:
            break

        # 发送一些数据到客户端
        sendData = raw_input("send:")
        newSocket.send(sendData)

    # 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
    newSocket.close()

# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接
tcpSerSocket.close()


3. 网络通信过程详解

 

3.1. Packet Tracer网络通信过程

Packet Tracer 介绍&安装

1. Packet Tracer介绍

Packet Tracer 是由Cisco(著名网络公司,思科)公司发布的一个辅助学习工具,

为学习思科网络课程的初学者去设计、配置、排除网络故障提供了网络模拟环境。

用户可以在软件的图形用户界面上直接使用拖曳方法建立网络拓扑,并可提供数据包在网络中行进的详细处理过程,观察网络实时运行情况。

2. 安装

学习网通信过程的重要性

在浏览器中输入 www.itcast.cn后,访问的整个过程有哪些?

 


3.2. 2台电脑组网


3.3. 通过集线器组网


3.4. 通过交换机组网


3.5. 通过路由器组网


3.6. 交换机、路由器、服务器组网


3.7. tcp三次挥手


3.8. tcp四次挥手


3.9. tcp十种状态


3.10. tcp的2MSL问题


3.11. tcp长连接和短连接


3.12. listen的队列长度


3.13. 手动配置ip


3.14. 常见网络攻击案例


3.15. 家庭上网解析


4. 并发服务器、HTTP协议

 

4.1. 单进程服务器


4.2. 多进程服务器


4.3. 多线程服务器


4.4. 单进程服务器-非堵塞模式


4.5. 单进程服务器-select版


4.6. 单进程服务器-epoll版


4.7. 多任务实现-协程


4.8. 协程-greenlet版


4.9. 协程-gevent版


4.10. 单进程服务器-gevent版

 

posted @ 2019-05-14 22:43  skorzeny  阅读(328)  评论(0编辑  收藏  举报