本文目录:
1.tcp/udp,端口,ip地址,子网掩码等简介
2.创建一个tcp的socket和udp的socket
3.udp详细
4.tftp
5.tcp详细
6.网络通信详细
7.并发服务器,Http协议,select,epoll
本文源码地址:点击打开链接
1.tcp/udp,端口,ip地址,子网掩码等简介
tcp/udp:百度百科—点击打开链接
早期的计算机网络,都是由各厂商自己规定一套协议,IBM、Apple和Microsoft都有各自的网络协议,互不兼容
为了把全世界的所有不同类型的计算机都连接起来,就必须规定一套全球通用的协议,为了实现互联网这个目标,互联网协议簇(Internet Protocol Suite)就是通用协议标准。
因为互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP协议,所以,大家把互联网的协议简称TCP/IP协议。
TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)协议属于传输层协议。其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。通俗说,它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送;而UDP则不为IP提供可靠性、流控或差错恢复功能。一般来说,TCP对应的是可靠性要求高的应用,而UDP对应的则是可靠性要求低、传输经济的应用。TCP支持的应用协议主要有:Telnet、FTP、SMTP等;UDP支持的应用层协议主要有:NFS(网络文件系统)、SNMP(简单网络管理协议)、DNS(主域名称系统)、TFTP(通用文件传输协议)等。
端口: 百度百科介绍—点击跳转
"端口"是英文port的意译,可以认为是设备与外界通讯交流的出口。端口可分为虚拟端口和物理端口,其中虚拟端口指计算机内部或交换机路由器内的端口,不可见。例如计算机中的80端口、21端口、23端口等。物理端口又称为接口,是可见端口,计算机背板的RJ45网口,交换机路由器集线器等RJ45端口。电话使用RJ11插口也属于物理端口的范畴。
如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口可以有65536(即:2^16)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(2^16-1)。
知名端口不能随便使用:知名端口是众所周知的端口号,范围从0到1023
动态端口的范围是从1024到65535
之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。
动态分配是指当一个系统进程或应用程序进程需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用。
当这个进程关闭时,同时也就释放了所占用的端口号。
用“netstat -an”查看端口状态
ip地址:百度百科—点击打开链接
IP地址是指互联网协议地址(英语:Internet Protocol Address,又译为网际协议地址),是IP Address的缩写。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。目前还有些ip代理软件,但大部分都收费。
子网掩码:百度百科—点击打开链接
子网掩码(subnet mask)又叫网络掩码、地址掩码、子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。
子网掩码是“255.255.255.0”的网络:
最后面一个数字可以在0~255范围内任意变化,因此可以提供256个IP地址。
但是实际可用的IP地址数量是256-2,即254个,因为主机号不能全是“0”或全是“1”。
主机号全为0,表示网络号
主机号全为1,表示网络广播
子网掩码例子:
IP地址为“192.168.1.1”子网掩码为“255.255.255.0”。
2.创建一个tcp的socket和udp的socket
socket简介:
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。
socket.socket(AddressFamily, Type)
两个参数:
Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)
例子:
#coding=utf-8
import socket
def createUDP():
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
print "创建了UDP"
def createTCP():
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print "创建了TCP"
if __name__ == '__main__':
createTCP()
createUDP()
3.udp详细
UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。 UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内。 UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。
UDP是面向消息的协议,通信时不需要建立连接,数据的传输自然是不可靠的,UDP一般用于多点通信和实时的数据业务,比如
语音广播
视频
QQ
TFTP(简单文件传送)
SNMP(简单网络管理协议)
RIP(路由信息协议,如报告股票市场,航空信息)
DNS(域名解释)
UDP发送/接收数据步骤:
发送例子:
# coding=utf-8
import socket
# 1.创建套接字
udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#2. 绑定本地的相关信息,如果一个网络程序不绑定,则系统会随机分配
bindAddr = ('', 8888) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddr)
# 3.准备接收方地址
sendAddr = ("192.168.1.2", 8080)
# 4.从键盘获取数据
sendData = "Hello,I'm UDP!"
# 5.发送数据到指定的电脑上
udpSocket.sendto(sendData, sendAddr)
# 6.关闭套接字
udpSocket.close()
print "完成了发送"
接收例子:
#coding=utf-8
import socket
# 1.创建UDP
udpSocket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#2.绑定本地ip,端口
bindAddr=('',8888) # ip,端口,默认为本机ip
udpSocket.bind(bindAddr)
# 3.等待接收方发送的数据(阻塞式)
recvData=udpSocket.recvfrom(1024) #每次接收1024个字节
# 4.显示接收的数据
print recvData
#5关闭套接字
udpSocket.close()
UDP广播本网络所有电脑
# coding=utf-8
import socket
dest = ('', 8888) #
# 创建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)
4.TFTP
TFTP: 百度百科—点击打开链接
TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69。
特点:
简单
占用资源小
适合传递小文件
适合在局域网进行传递
端口号为69
基于UDP实现
5.tcp详细
百度百科—点击打开链接
TCP协议基于三次握手机制,安全可靠性更高。
TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
TCP服务端流程:
1.socket创建一个套接字
2.bind绑定ip和port
3.listen使套接字变为可以被动链接
4.accept等待客户端的链接
5.recv/send接收发送数据
简单TCP服务端代码:
#coding=utf-8
from socket import *
#1.创建socket
tcpServerSocket=socket(AF_INET,SOCK_STREAM)
#2.绑定本地信息
address=('',7788)
tcpServerSocket.bind(address=address)
#3.使用socket创建的套接字默认的属性是主动的,使用listen将其变被动的,这样就可以接收别人的链接了
tcpServerSocket.listen(5)
#listen中的black表示已经建立链接和半链接的总数
#如果当前已建立链接数和半链接数以达到设定值,那么新客户端就不会connect成功,而是等待服务器
#4. 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器# newSocket用来为这个客户端服务# tcpSerSocket就可以省下来专门等待其他新客户端的链接newSocket,clientAddr=tcpServerSocket.accept()#5. 接收对方发送过来的数据,最大接收1024个字节recvData=newSocket.recv(1024)print "接收到的数据为:",recvData# 6.发送一些数据到客户端newSocket.send("Thank you!")# 7.关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接newSocket.close()# 8.关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接tcpServerSocket.close()
#coding=utf-8
from socket import *
# 1.创建socket
tcpClientSocket=socket(AF_INET,SOCK_STREAM)
# 2.链接到服务器
serverAddr=('192.168.1.2',7788)
tcpClientSocket.connect(serverAddr)
# 3.输入数据
sendData="I'm Client!"
tcpClientSocket.send(sendData)
# 4.接收对方发送过来的数据,最大接受1024字节
recvData=tcpClientSocket.recv(1024)
print "接收到的数据为:",recvData
# 5.关闭套接字
tcpClientSocket.close()
短连接的操作步骤是:
建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接
长连接的操作步骤是:
建立连接——数据传输...(保持连接)...数据传输——关闭连接
TCP短连接流程:
1.client 向 server 发起连接请求
2.server 接到请求,双方建立连接
3.client 向 server 发送消息
4.server 回应 client
5.一次读写完成,此时双方任何一个都可以发起 close 操作
在第 步骤5中,一般都是 client 先发起 close 操作。当然也不排除有特殊的情况。
从上面的描述看,短连接一般只会在 client 和server 间传递一次读写操作!
TCP长连接流程:
1.client 向 server 发起连接
2.server 接到请求,双方建立连接
3.client 向 server 发送消息
4.server 回应 client
5.一次读写完成,连接不关闭
6.后续读写操作...
7.长时间操作之后client发起关闭请求
TCP长/短连接的优点和缺点
长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。
对于频繁请求资源的客户来说,较适用长连接。
client与server之间的连接如果一直不关闭的话,会存在一个问题,
随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,
如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致server端服务受损;
如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,
这样可以完全避免某个蛋疼的客户端连累后端服务。
短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。
但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。
TCP长/短连接的应用场景
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。
每个TCP连接都需要三次握手,这需要时间,如果每个操作都是先连接,
再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,
再次处理时直接发送数据包就OK了,不用建立TCP连接。
例如:数据库的连接用长连接,如果用短连接频繁的通信会造成socket错误,
而且频繁的socket 创建也是对资源的浪费。
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,
而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,
如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,
那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
7.网络攻击(network attack):
维基百科—点击打开链接
8.并发服务器,Http协议,select,epoll
并发服务器:
百度百科—点击打开链接
Http协议:
百度百科—点击打开链接
select:
IO多路复用的模型中,比较常用的有select模型和epoll模型。这两个都是系统接口,由操作系统提供。当然,Python的select模块进行了更高级的封装。
网络通信被Unix系统抽象为文件的读写,通常是一个设备,由设备驱动程序提供,驱动可以知道自身的数据是否可用。支持阻塞操作的设备驱动通常会实现一组自身的等待队列,如读/写等待队列用于支持上层(用户层)所需的block或non-block操作。设备的文件的资源如果可用(可读或者可写)则会通知进程,反之则会让进程睡眠,等到数据到来可用的时候,再唤醒进程。
这些设备的文件描述符被放在一个数组中,然后select调用的时候遍历这个数组,如果对于的文件描述符可读则会返回改文件描述符。当遍历结束之后,如果仍然没有一个可用设备文件描述符,select让用户进程则会睡眠,直到等待资源可用的时候在唤醒,遍历之前那个监视的数组。每次遍历都是依次进行判断的。
优点:
select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点。
缺点:
select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样也会造成效率的降低。
一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max察看。32位机默认是1024个。64位机默认是2048.
对socket进行扫描时是依次扫描的,即采用轮询的方法,效率较低。
当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。
epoll的优点:
没有最大并发连接的限制,能打开的FD(指的是文件描述符,通俗的理解就是套接字对应的数字编号)的上限远大于1024
效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数;即epoll最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关,因此在实际的网络环境中,epoll的效率就会远远高于select和poll。