实训一阶段1:基本网络通信
要求:
开发一个聊天程序;
包含客户端和服务器端;
编程语言不限;
要能在两台PC上运行。
初级阶段1:socket使用
在TCP中,客户端的实现流程:(1)创建客户端的socket对象 (2)建立与服务器之间的联系 (3)发送请求 (4)接收数据 (5)关闭连接
服务端的实现流程:(1)创建服务端的socket对象 (2)绑定服务端的地址 (3)设置监听器 (4)等待客户端的连接 (5)接收客户端的请求 (6)返回处理的结果到客户端
套接字(Socket) ,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口
应用程序接口 (英语:A pplication P rogramming I nterface,简称:API ),又称为应用编程接口 ,就是软件 系统不同组成部分衔接的约定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 socket编程思路 TCP服务端: 1 创建套接字,绑定套接字到本地IP与端口 # socket.socket(socket.AF_INET,socket.SOCK_STREAM) , s.bind() 2 开始监听连接 #s.listen() 3 进入循环,不断接受客户端的连接请求 #s.accept() 4 然后接收传来的数据,并发送给对方数据 #s.recv() , s.sendall() 5 传输完毕后,关闭套接字 #s.close() TCP客户端: 1 创建套接字,连接远端地址 # socket.socket(socket.AF_INET,socket.SOCK_STREAM) , s.connect() 2 连接后发送数据和接收数据 # s.sendall(), s.recv() 3 传输完毕后,关闭套接字 #s.close()
subprocess 模块 允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。
Python3 网络编程
Python 提供了两个级别访问的网络服务。:
低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
网络中进程间如何通信,即利用三元组【ip地址,协议,端口】可以进行网络间通信了,那我们应该怎么实现了,因此,我们socket应运而生,它就是利用三元组解决网络通信的一个中间件工具
TCP建立连接时要传输三个数据包,俗称三次握手(Three-way Handshaking)。
1 2 3 [Shake 1 ] 套接字A:“你好,套接字B,我这里有数据要传送给你,建立连接吧。” [Shake 2 ] 套接字B:“好的,我这边已准备就绪。” [Shake 3 ] 套接字A:“谢谢你受理我的请求。
服务器端套接字
s.bind()
绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。
s.listen()
开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。 listen函数中backlog的含义是什么?完成队列的长度 (https://zhuanlan.zhihu.com/p/78879634 )
s.accept()
被动接受TCP客户端连接,(阻塞式)等待连接的到来
客户端套接字
s.connect()
主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
公共用途的套接字函数
s.recv()
接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
s.send()
发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。
s.close()
关闭套接字
代码0.1
作用:可以实现服务端和客户端简单交互,但仅限同一个局域网内,且一对一,只能发送一句话
1 2 3 4 5 6 7 8 9 10 11 12 错误类型: 1.LookupError: unknown encoding: uft-8 这个错误是记录错误类型的,第一次遇到LookupError ,这个是编码格式本来应该是utf-8 自己打字的时候打错了,打成uft-8 了 所以就出现了这个错误. 2.AttributeError: 'tuple' object has no attribute 'send' 错误原因: server.accept()的返回值是一对(conn, address),其中conn是一个新的套接字对象,可用于在连接上发送和接收数据,地址是绑定到连接另一端的套接字的地址。 解决方法:client,addr = server.accept() 3.TimeoutError: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。 防火墙没开放该端口网上找到这个……经过24小时检验:socket仅限在局域网使用,所以……一个热点IP和学校内网一起玩……不可能,想的话买个服务器。所以要么开两个学校电脑,要么就在自己电脑上玩耍。 host='服务器的静态IP'(IPv4地址) host = socket.gethostbyname(socket.gethostname()) (土豆那缺儿,我们一直检验都连不起来原来它是IPv4网关……) 4. 这个是端口号未开放的原因,在防火墙里开放就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import sockethost = '192.168.31.129' port = 8800 print (host)client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect((host,port)) msg = client.recv(1024 ) client.close() print (msg.decode('utf-8' ))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import sockethost = '192.168.120.209' port = 8800 print (host)server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((host,port)) server.listen(1 ) while True : client,addr = server.accept() print ("连接地址:%s" %str (addr)) msg = 'Hello!' client.send(msg.encode('utf-8' )) client.close()
为什么多个客户端可以连接服务器的同个端口?
我们这里讲Socket连接:
1.端口只是一个数字辨识,不是真正的物理端口;
2.一个Socket连接的主键 (即不同socket之间的区分)是由一个五元组{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}组成,即{源地址,源端口,目标地址,目标端口,协议}组成,那些说四元组不包含协议的说法是错误的。
3.一个进程可以拥有多个socket连接。
例子一、两个客户端连接在同个服务器的同个端口80,即有两个socket连接:
- socket1 {SRC-A, 100, DEST-X,80, TCP}
- socket2{SRC-B, 100, DEST-X,80, TCP}
主机A和主机B的地址不同,两台主机同时连接到服务器X的80端口。服务器要怎么处理这个连接是它的事,我们要理解的是为什么一个主机同个端口能监听多个客户端Socket连接。
解释:
1.是因为两个客户端的IP不同,服务器能识别出不同的Socket;
2.即使IP地址相同,端口不同,服务器也能够分辨;
3.只要服务器知道收到的请求和哪个socket相关,那么它就能使用这个socket正确地回复那个客户端;
4.如果对于不同的socket需要不同的端口,那么不仅仅浪费服务器资源,而且每次客户端连接上serverSocket之后还要另外分配新的端口和客户端通信。没必要。
例子二、不同的进程可以监听同一个端口。
因此在服务器的两个使用不同协议的进程可以监听同一个端口。
如果一个socket的辨识只是四元组不包括协议{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT},那么不同进程是不可能同时监听同一个端口的。没有协议的话一个客户端连接到同一台某个有两个进程监听端口的服务器,那么就没有什么机制可以确定客户端是要连接哪一个进程了。
总结:
不同协议可以监听同一个端口(不管是不是在服务器的同个进程)
某个协议的进程可以监听多个客户端的连接,因为只要五元组不同进程就能分辨。
从上面的例子可以知道,客户端同个进程也可以在同个端口用不同的协议与客户端建立连接。
一、Socket技术详解 - 简书 (jianshu.com)
代码0.2
作用:在0.1基础上,实现服务器接收数据,客户端发送数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import sockethost = socket.gethostname() port = 9999 print (host)server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((host,port)) server.listen(2 ) while True : client,addr = server.accept() print ("连接地址:%s" %str (addr)) msg = client.recv(1024 ) print (msg.decode('utf-8' )) client.close()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import sockethost = socket.gethostname() port = 9999 print (host)client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect((host,port)) msg = 'Hello!' client.send(msg.encode('utf-8' )) client.close()
代码0.3
作用:在0.2基础上,实现可传可接收,但存在问题,未解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import sockethost = socket.gethostname() port = 8800 max_connect = 1 max_receive_data = 1024 server_name = '老王' server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((host,port)) server.listen(max_connect) print ('Server is ready.' )while True : client,addr = server.accept() print ("连接地址:%s" %str (addr)) send_msg = input ('请输入:' ) send_msg = server_name + ': ' + send_msg client.send(send_msg.encode('utf-8' )) if send_msg == 'close' : break receive_msg = client.recv(max_receive_data) print (receive_msg.decode('utf-8' )) client.close()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import sockethost = socket.gethostname() port = 8800 max_receive_data = 1024 client_name = '老刘' client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect((host,port)) print ('Connecting is successful!' )while True : receive_msg = client.recv(max_receive_data) print (receive_msg.decode('utf-8' )) if receive_msg.decode('utf-8' )=='close' : break send_msg = input ('请输入:' ) send_msg = client_name + ': ' + send_msg client.send(send_msg.encode('utf-8' )) client.close()
初级阶段2:threading使用
1 2 服务器端的套接字起到监听的作用(类似电话主机),每连接成功一个客户端,就返回一个和客户端通信的套接字(类似电话的分机),服务器端用每个“分机”和每个客户端进行通信。 因为我们使用的是默认的阻塞套接字,服务器和每个客户端通信的过程都是阻塞的,所以,为了服务器可以“同时”(并发)和客户端进行通信,我们用到了多线程。
hreading(多线程)模块中包含了关于线程操作的丰富功能,包括:常用线程函数,线程对象,锁对象,递归锁对象,事件对象,条件变量对象,信号量对象,定时器对象,栅栏对象。
创建 Thread 对象有 2 种手段:
1.直接创建 Thread ,将一个 callable 对象从类的构造器传递进去,这个 callable 就是回调函数,用来处理任务。
2.编写一个自定义类继承 Thread,然后复写 run() 方法,在 run() 方法中编写任务处理代码,然后创建这个 Thread 的子类。
(29条消息) Python多线程编程(一):threading 模块 Thread 类的用法详解_frank909的博客-CSDN博客_python threading
Python 将一个列表里面的元素拼接成一个字符串:
注意: 1. 列表里面的元素必须全是字符串才可以使用join()进行拼接
2. 返回的是一个字符串
1 2 item1 = ["lowman" , "isbusy" ] item2 = "," .join(item1)
Thread.setDaemon(false)设置为用户线程;通过Thread.setDaemon(true)设置为守护线程。如果不设置次属性,默认为用户线程。
用户线程和守护线程的区别:
1.主线程结束后用户线程还会继续运行,JVM存活;主线程结束后守护线程和JVM的状态又下面第2条确定。
2.如果没有用户线程,都是守护线程,那么JVM结束(随之而来的是所有的一切烟消云散,包括所有的守护线程)。
(29条消息) Thread.setDaemon详解_starfe-geek的博客-CSDN博客_thread.setdeamon
Threading模块的对象
描述
Thread
线程对象
Threading模块的Thread类
描述
name
线程名(属性)
ident
线程标识符(属性)
daemon
线程是否是守护线程(属性)
init (group=None, tatget=None, name=None, args=(),kwargs ={}, verbose=None, daemon=None)
实例化一个线程对象,需要有一个可调用的 target,以及其参数 args或 kwargs。还可以传递 name 或 group 参数,不过后者还未实现。此外, verbose 标 志 也 是 可 接 受 的。 而 daemon 的 值 将 会 设定thread.daemon 属性/标志
start()
开启线程
run()
定义线程功能的方法(通常在子类中被应用开发者重写)
(29条消息) Python3——多线程之threading模块_a1314521531的博客-CSDN博客_python3 threading
Python中获取异常(Exception)信息
repr(e)
给出较全的异常信息,包括异常信息的类型,如1/0的异常信息
“ZeroDivisionError(‘integer division or modulo by zero’,)”
代码0.4
作用:在0.3基础上实现多客户端交流,但发送数据和接收数据(显示)安排不合理
(29条消息) python实现简易聊天室程序_Castria的博客-CSDN博客_python聊天室项目代码
首先服务器端创建ServerSocket对象,等待客户连接。
每当有一个客户连接上时,使用一个线程保存其Socket,把该线程保存在一个HashMap集合中。
客户端有信息发送给服务器时,服务器先获取要接收者用户名,根据用户名获取保存的线程(如果没有找到该线程则回发给发送者消息提示其需要联系的用户未上线),再根据该线程创建输出流,把消息转发给接收者。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 import socketimport threadinghost = socket.gethostname() port = 9999 max_connect = 2 max_recedata = 1024 print (host)server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((host, port)) server.listen(max_connect) print ('ServerSocket is ready.' )cnt = 0 textList = [] socketList = [] class ThreadCreate (threading.Thread ): def __init__ (self, client ): threading.Thread.__init__(self) self.client = client socketList.append(client) def run (self ): try : global cnt for sock in socketList: if sock == self.client: sock.send(('Old client.There are %d presons.' %(cnt)).encode('utf-8' )) else : sock.send(('New Client is Coming.There are %d presons.' %(cnt)).encode('utf-8' )) while True : word = self.client.recv(max_recedata).decode() textList.append(word) for sock in socketList: sock.send(('\n' +word).encode('utf-8' )) except Exception as e: print (repr (e)) cnt = cnt-1 print ('Lose one person.There are %d persons.' %(cnt)) socketList.remove(self.client) for sock in socketList: sock.send(('Lose one person.There are %d persons.' %(cnt)).encode()) while True : client, addr = server.accept() print ("连接地址:%s" % str (addr)) try : if len (textList) == 0 : client.send('No message.' .encode('utf-8' )) else : client.send('\n' .join(textList).encode('utf-8' )) cnt = cnt + 1 newThread = ThreadCreate(client) newThread.setDaemon(True ) newThread.start() print ('Connecting is successful!The number of people is ' + str (cnt) + '.' ) except Exception as e: print (repr (e))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import socketimport threadingserver_host = socket.gethostname() server_port = 9999 max_recedata = 1024 client_name = 'Nacy' print (server_host)client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) print ('Connecting......' )client.connect((server_host,server_port)) print ('Connecting is successful!' )msg = client.recv(max_recedata) if msg.decode('utf-8' )!='No message.' : print (msg.decode('utf-8' )+'\n------以上是历史消息------\n' ) class ThreadReceive (threading.Thread ): def __init__ (self ): threading.Thread.__init__(self) def run (self ): while True : receive_msg = client.recv(max_recedata) print (receive_msg.decode('utf-8' )) textThread = ThreadReceive() textThread.start() def send (): while True : send_msg = input ('请输入:' ) if send_msg=='0' : break client.send((client_name+': ' +send_msg).encode('utf-8' )) send()
代码0.5
作用:在0.4基础上加了时间戳,将input里的字符删了,直接输就行……
(29条消息) Python 给某个文件名添加时间戳_cheney康的博客-CSDN博客
(29条消息) python:threading.Thread类的使用详解_啊啊啊西吧的博客-CSDN博客_python thread
python中的多线程锁lock=threading.Lock()如何使用 - 开发技术 - 亿速云 (yisu.com)
1 2 3 4 5 6 7 8 mutex = threading.Lock() #锁的使用 #创建锁 mutex = threading.Lock() #锁定 mutex.acquire([timeout]) #释放 mutex.release()
发现没啥要修改的……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 import socketimport threadinghost = socket.gethostname() port = 9999 max_connect = 2 max_recedata = 1024 print (host)server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((host, port)) server.listen(max_connect) print ('ServerSocket is ready.' )cnt = 0 textList = [] socketList = [] class ThreadCreate (threading.Thread ): def __init__ (self, client ): threading.Thread.__init__(self) self.client = client socketList.append(client) def run (self ): try : global cnt for sock in socketList: if sock == self.client: sock.send(('Welcome!There are %d presons.' %(cnt)).encode('utf-8' )) else : sock.send(('New Client is Coming.There are %d presons.' %(cnt)).encode('utf-8' )) while True : word = self.client.recv(max_recedata).decode() textList.append(word) for sock in socketList: sock.send(('\n' +word).encode('utf-8' )) except Exception as e: print (repr (e)) cnt = cnt-1 print ('Lose one person.There are %d persons.' %(cnt)) socketList.remove(self.client) for sock in socketList: sock.send(('Lose one person.There are %d persons.' %(cnt)).encode()) while True : client, addr = server.accept() print ("连接地址:%s" % str (addr)) try : if len (textList) == 0 : client.send('No message.' .encode('utf-8' )) else : client.send('\n' .join(textList).encode('utf-8' )) cnt = cnt + 1 newThread = ThreadCreate(client) newThread.setDaemon(True ) newThread.start() print ('Connecting is successful!The number of people is ' + str (cnt) + '.' ) except Exception as e: print (repr (e))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import threadingserver_host = socket.gethostname() server_port = 9999 max_recedata = 1024 client_name = 'Helen' print (server_host)lock = threading.Lock() client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) print ('Connecting......' )client.connect((server_host,server_port)) print ('Connecting is successful!' )msg = client.recv(max_recedata) if msg.decode('utf-8' )!='No message.' : print (msg.decode('utf-8' )+'\n------以上是历史消息------\n' ) class ThreadReceive (threading.Thread ): def __init__ (self ): threading.Thread.__init__(self) def run (self ): while True : receive_msg = client.recv(max_recedata) print (receive_msg.decode('utf-8' )) textThread = ThreadReceive() textThread.start() def send (): while True : send_msg = input () if send_msg == '0' : break client.send((client_name+': ' +send_msg).encode('utf-8' )) send()
初级阶段3:可视化
代码0.6
作用:有问题,修理中……主要是服务器老炸了……可能是类的原因
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 import wximport socketimport threadingdef getIP (): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8" , 80 )) ip=s.getsockname()[0 ] return ip host = getIP() port = 8000 max_connect = 2 max_recedata = 2048 print (host)cnt = 0 textList = [] socketList = [] class ThreadCreate (threading.Thread ): def __init__ (self, client ): threading.Thread.__init__(self) self.client = client socketList.append(client) def run (self ): try : global cnt for sock in socketList: if sock == self.client: sock.send(('Welcome!There are %d presons.' %(cnt)).encode()) else : sock.send(('New Client is Coming.There are %d presons.' %(cnt)).encode()) while True : word = self.client.recv(max_recedata).decode() textList.append(word) for sock in socketList: sock.send(('\n' +word).encode()) except Exception as e: print (repr (e)) cnt = cnt-1 print ('Lose one person.There are %d persons.' %(cnt)) socketList.remove(self.client) for sock in socketList: sock.send(('Lose one person.There are %d persons.' %(cnt)).encode()) class Frame (wx.Frame ): def __init__ (self ): wx.Frame.__init__(self, None , title='多人聊天系统(服务器)' , size=(400 , 300 ),name='frame' ,style=541072960 ) self.qdck = wx.Panel(self) self.qdck.SetOwnBackgroundColour((255 , 255 , 255 , 255 )) self.Centre() self.an1 = wx.Button(self.qdck,size=(120 , 40 ),pos=(44 , 160 ),label='启动客户端' ,name='button' ) self.an1.SetAuthNeeded(True ) self.an1.Bind(wx.EVT_BUTTON,self.an1_anbdj) self.an2 = wx.Button(self.qdck,size=(120 , 40 ),pos=(227 , 160 ),label='关闭客户端' ,name='button' ) self.an2.SetAuthNeeded(True ) self.an2.Bind(wx.EVT_BUTTON,self.an2_anbdj) self.bq1 = wx.StaticText(self.qdck,size=(240 , 40 ),pos=(80 , 35 ),label='多人聊天系统客户端' ,name='staticText' ,style=2321 ) bq1_字体 = wx.Font(16 ,70 ,90 ,400 ,False ,'Microsoft YaHei UI' ,-1 ) self.bq1.SetFont(bq1_字体) def an1_anbdj (self,event ): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((host, port)) server.listen(max_connect) print ('ServerSocket is ready.' ) while True : client, addr = server.accept() print ("连接地址:%s" % str (addr)) try : global cnt if len (textList) == 0 : client.send('No message.' .encode()) else : client.send('\n' .join(textList).encode()) cnt = cnt + 1 newThread = ThreadCreate(client) newThread.setDaemon(True ) newThread.start() print ('Connecting is successful!The number of people is ' + str (cnt) + '.' ) except Exception as e: print (repr (e)) def an2_anbdj (self,event ): print ('an2,按钮被单击' ) class myApp (wx.App ): def OnInit (self ): self.frame = Frame() self.frame.Show(True ) return True if __name__ == '__main__' : app = myApp() app.MainLoop()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 import wximport socketimport threadingfrom time import sleep, localtimefrom datetime import datetimeserver_host = socket.gethostname() server_port = 8000 max_recedata = 2048 client_name = socket.gethostname() print (server_host)lock = threading.Lock() host_ip = '' client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) class chuangkou (wx.Frame ): def __init__ (self ): self.liaotian = 0 super (chuangkou, self).__init__(None , -1 , title="多人聊天程序" , size=(600 , 600 )) self.a = wx.Panel(self) self.ip=wx.TextCtrl(self.a,style=wx.TE_PROCESS_ENTER ,value="请输入服务器的ip地址" ) self.b = wx.Button(self.a, wx.ID_ANY, "确定" ) self.b.SetAuthNeeded(True ) self.b.Bind(wx.EVT_BUTTON, self.b_anbdj) self.text = wx.TextCtrl(self.a, style=wx.TE_READONLY | wx.TE_MULTILINE | wx.TE_RICH2 | wx.BORDER_SIMPLE | wx.HSCROLL) self.text.SetBackgroundColour('#d1d1d1' ) self.ctrl = wx.TextCtrl(self.a, style=wx.TE_PROCESS_ENTER | wx.TE_MULTILINE,value="" ) self.sent = wx.Button(self.a, wx.ID_ANY, "发送" ) self.sent.SetAuthNeeded(True ) self.sent.Bind(wx.EVT_BUTTON, self.sent_anbdj) box = wx.BoxSizer(wx.HORIZONTAL) box1 = wx.BoxSizer(wx.VERTICAL) box1.Add(self.ip,proportion=3 , flag=wx.EXPAND|wx.TOP,border=0 ) box1.Add(self.b, proportion=1 , flag=wx.EXPAND | wx.TOP, border=0 ) box1.Add(self.text, proportion=30 , flag=wx.EXPAND | wx.TOP, border=0 ) box1.Add(self.ctrl, proportion=20 , flag=wx.EXPAND | wx.TOP, border=0 ) box1.Add(self.sent, proportion=3 , flag=wx.EXPAND | wx.TOP, border=0 ) self.a.SetSizer(box1) self.msg='' def b_anbdj (self,event ): global msg host_ip=self.ip.GetValue() toastone = wx.MessageDialog(None , "链接的服务器地址为" +host_ip, "信息提示" , wx.YES_DEFAULT | wx.ICON_QUESTION) if toastone.ShowModal() == wx.ID_YES: toastone.Destroy() client.connect((host_ip, server_port)) toastone = wx.MessageDialog(None , "Connecting is successful!" , "信息提示" , wx.YES_DEFAULT | wx.ICON_QUESTION) if toastone.ShowModal() == wx.ID_YES: toastone.Destroy() def sent_anbdj (self,event ): send_msg = self.ctrl.GetValue() client.send((client_name + ': ' + send_msg).encode()) def ThreadReceive (self ): while True : self.msg = client.recv(max_recedata) self.text.AppendText(self.msg.decode() + "\n\n" ) if __name__ == '__main__' : app = wx.App() shili = chuangkou() shili.Show() app.MainLoop()
初级阶段4:线程改版+tkinter使用
0.5
作用:换了个线程控制方式
变化:
1 2 server.listen() #监听 server = socket.socket() #创建server对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 import socketimport threadinghost = socket.gethostname() port = 8000 SocketList = [] TextList = [] cnt = 0 print (host)server = socket.socket() server.bind((host,port)) server.listen() print ('服务器准备就绪!' )def read_client (s ): try : return s.recv(2048 ).decode('utf-8' ) except : print (str (addr)+'已下线!' ) SocketList.remove(s) def send_client (s ): try : while True : content = read_client(s) if content is None : break else : TextList.append(str (addr)+': ' +content) for sock in SocketList: sock.send((str (addr)+': ' +content).encode('utf-8' )) except : print ('广播未成功!' ) while True : client,addr = server.accept() SocketList.append(client) print (str (addr)+'已加入!' ) try : if len (TextList)==0 : client.send('No message.' .encode('utf-8' )) else : client.send('\n' .join(TextList).encode('utf-8' )) cnt = cnt + 1 threading.Thread(target=send_client, args=(client,)).start() except Exception as e: print (repr (e))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import socketimport threadingserver_host = socket.gethostname() server_port = 8000 client = socket.socket() print ('Connecting......' )client.connect((server_host,server_port)) print ('Connecting is successful!' )content = client.recv(2048 ).decode('utf-8' ) if content != 'No message.' : print (content + '\n------以上是历史消息------\n' ) def read_server (c ): while True : content = c.recv(2048 ).decode('utf-8' ) print (content) threading.Thread(target=read_server, args=(client,)).start() while True : word = input () if word == 'close' : break client.send(word.encode('utf-8' ))
0.6
作用:0.5基础上优化(nickname)+进行图形界面可视化;
Python 提供了多个图形开发界面的库,几个常用 Python GUI 库如下:
Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。
注意 *:Python3.x 版本使用的库名为 tkinter,即首写字母 T 为小写*
创建一个GUI程序
1、导入 Tkinter 模块
2、创建控件
3、指定这个控件的 master, 即这个控件属于哪一个
4、告诉 GM(geometry manager) 有一个控件产生了。
[Python GUI 编程(Tkinter) | 菜鸟教程 (runoob.com )](https://www.runoob.com/python/python-gui-tkinter.html#:~:text=Tkinter 是 Python 的标准 GUI 库。 Python 使用,Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。)
(29条消息) TK-StringVar_Eider1998的博客-CSDN博客_stringvar()作用
Python Tkinter 框架控件(Frame) | 菜鸟教程 (runoob.com)
(29条消息) python弹窗——tkinter.messagebox学习总结_鹿鹿有为啊的博客-CSDN博客_python tkinter 弹窗
tkinter的set()与get() - 做梦者造梦 - 博客园 (cnblogs.com)
(29条消息) tkinter库最全使用教程_千禧皓月的博客-CSDN博客_tkinter
(29条消息) 用tkinter.pack设计复杂界面布局_快乐清风客的博客-CSDN博客_tkinter复杂界面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 import socketimport threadinghost = socket.gethostname() port = 8000 SocketList = [] TextList = [] Nickname = [] cnt = 0 print (host)server = socket.socket() server.bind((host,port)) server.listen() print ('服务器准备就绪!' )def read_client (s,nickname ): try : return s.recv(2048 ).decode('utf-8' ) except : print (nickname + '已下线!' ) SocketList.remove(s) Nickname.remove(nickname) for sock in SocketList: sock.send(('系统消息:' + nickname + '已下线!' ).encode('utf-8' )) def send_client (s,nickname ): try : s.send((',' .join(Nickname)).encode('utf-8' )) while True : content = read_client(s) if content is None : break else : TextList.append(nickname + ': ' + content) for sock in SocketList: sock.send((nickname + ': ' + content).encode('utf-8' )) except : print ('广播未成功!' ) while True : client,addr = server.accept() SocketList.append(client) try : nickname = client.recv(2048 ).decode('utf-8' ) if nickname in Nickname: i = 1 while True : if nickname+str (i) in Nickname: i = i+1 else : nickname = nickname + str (i) break Nickname.append(nickname) print (nickname + '已加入!' ) for sock in SocketList: sock.send(('系统消息:' + nickname + '已加入!' ).encode('utf-8' )) if len (TextList)==0 : client.send('No message.' .encode('utf-8' )) else : client.send('\n' .join(TextList).encode('utf-8' )) cnt = cnt + 1 threading.Thread(target=send_client, args=(client,nickname,)).start() except Exception as e: print (repr (e))
0.65
作用:0.6基础上的修改(显示在线人数和历史消息暂时删了,仅保留了聊天功能),先能用……还要解决子线程如何关闭的问题……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 import socketimport threadinghost = socket.gethostname() port = 9999 SocketList = [] TextList = [] Nickname = [] cnt = 0 print (host)server = socket.socket() server.bind((host,port)) server.listen() print ('服务器准备就绪!' )def read_client (s,nickname ): try : return s.recv(2048 ).decode('utf-8' ) except : print (nickname + '已下线!' ) SocketList.remove(s) Nickname.remove(nickname) for sock in SocketList: sock.send(('系统消息:' + nickname + '已下线!' ).encode('utf-8' )) def send_client (s,nickname ): try : while True : content = read_client(s,nickname) if content is None : break else : TextList.append(nickname + ': ' + content) for sock in SocketList: sock.send((nickname + ': ' + content).encode('utf-8' )) except Exception as e: print ('广播未成功!' ) while True : client,addr = server.accept() SocketList.append(client) nickname = client.recv(2048 ).decode('utf-8' ) if nickname in Nickname: i = 1 while True : if nickname+str (i) in Nickname: i = i+1 else : nickname = nickname + str (i) break Nickname.append(nickname) print (nickname + '已加入!' ) for sock in SocketList: sock.send(('系统消息:' + nickname + '已加入!' ).encode('utf-8' )) cnt = cnt + 1 threading.Thread(target=send_client, args=(client,nickname,)).start()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 import socketimport threadingfrom tkinter import *import tkinter.messagebox from tkinter import scrolledtext server_host = socket.gethostname() server_port = 9999 client = socket.socket() print ('Connecting......' )def LoginWindow (): root = Tk() root.title('一起来聊天 · 登录' ) root.geometry('300x150' ) root.geometry('+500+300' ) nickname = StringVar() root.resizable(0 , 0 ) def Login_in (): name = nickname.get() if not name: tkinter.messagebox.showwarning('Warning' , message='用户名为空!' ) elif len (name) > 10 : tkinter.messagebox.showwarning('Warning' , message='用户名过长!最多为十个字符!' ) else : root.destroy() client.connect((server_host, server_port)) print ('Connecting is successful!' ) client.send(name.encode('utf-8' )) ChatRoom(name) Button(root, text="登录" , command=Login_in, width=8 , height=1 ).place(x=100 , y=90 , width=100 , height=35 ) Label(root, text='请输入昵称' , font=('Fangsong' , 12 )).place(x=10 , y=20 , height=50 , width=80 ) Entry(root, textvariable=nickname, font=('Fangsong' , 11 )).place(x=100 , y=30 , height=30 , width=180 ) root.mainloop() def ChatRoom (nickname ): root = Tk() root.geometry('650x400' ) root.resizable(0 , 0 ) root.geometry('+500+300' ) root.title('一起来聊天 · ' + nickname) content = client.recv(2048 ).decode('utf-8' ) ChatBox = scrolledtext.ScrolledText(root) ChatBox.place(x=5 , y=0 , width=500 , height=300 ) ChatBox.insert('end' ,content) def read_server (c ): while True : content = c.recv(2048 ).decode('utf-8' ) ChatBox.insert('end' , '\n' +content+'\n\n' ) ChatBox.see(tkinter.END) ChatBox.update() threading.Thread(target=read_server, args=(client,)).start() word = StringVar() word.set ('' ) SentBox = Entry(root,width=140 ,textvariable=word) SentBox.place(x=5 ,y=305 ,width=600 ,height=95 ) def sendtext (): content = word.get() if content=='end' : client.close() client.send(content.encode('utf-8' )) word.set ('' ) sendButton = Button(root, text='发 送' , font=('Fangsong' , 18 ), bg='white' , command=sendtext) sendButton.place(x=500 , y=305 , width=150 , height=95 ) root.mainloop() LoginWindow()
0.67
作用:0.65上改了点细节(可视化界面加了个图片),先能用……要解决子线程关闭问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 import socketimport threadinghost = socket.gethostname() port = 9999 SocketList = [] TextList = [] Nickname = [] cnt = 0 print (host)server = socket.socket() server.bind((host,port)) server.listen() print ('服务器准备就绪!' )def read_client (s,nickname ): try : return s.recv(2048 ).decode('utf-8' ) except : print (nickname + '已下线!' ) SocketList.remove(s) Nickname.remove(nickname) for sock in SocketList: sock.send(('系统消息:' + nickname + '已下线!' ).encode('utf-8' )) def send_client (s,nickname ): try : while True : content = read_client(s,nickname) if content is None : break else : TextList.append(nickname + ': ' + content) for sock in SocketList: sock.send((nickname + ': ' + content).encode('utf-8' )) except Exception as e: print ('广播未成功!' ) while True : client,addr = server.accept() SocketList.append(client) nickname = client.recv(2048 ).decode('utf-8' ) if nickname in Nickname: i = 1 while True : if nickname+str (i) in Nickname: i = i+1 else : nickname = nickname + str (i) break Nickname.append(nickname) print (nickname + '已加入!' ) for sock in SocketList: sock.send(('系统消息:' + nickname + '已加入!' ).encode('utf-8' )) cnt = cnt + 1 threading.Thread(target=send_client, args=(client,nickname,)).start()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 import socketimport threadingfrom tkinter import *import tkinter.messagebox from tkinter import scrolledtext server_host = socket.gethostname() server_port = 9999 client = socket.socket() print ('Connecting......' )def LoginWindow (): root = Tk() root.title('一起来聊天 · 登录' ) root.geometry('300x150' ) root.geometry('+500+300' ) nickname = StringVar() root.resizable(0 , 0 ) def Login_in (): name = nickname.get() if not name: tkinter.messagebox.showwarning('Warning' , message='用户名为空!' ) elif len (name) > 10 : tkinter.messagebox.showwarning('Warning' , message='用户名过长!最多为十个字符!' ) else : root.destroy() client.connect((server_host, server_port)) print ('Connecting is successful!' ) client.send(name.encode('utf-8' )) ChatRoom(name) Button(root, text="登录" , command=Login_in, width=8 , height=1 ).place(x=100 , y=90 , width=100 , height=35 ) Label(root, text='请输入昵称' , font=('Fangsong' , 12 )).place(x=10 , y=20 , height=50 , width=80 ) Entry(root, textvariable=nickname, font=('Fangsong' , 11 )).place(x=100 , y=30 , height=30 , width=180 ) root.mainloop() def ChatRoom (nickname ): root = Tk() root.geometry('650x400' ) root.resizable(0 , 0 ) root.geometry('+500+300' ) root.title('一起来聊天 · ' + nickname) img_png = PhotoImage(file='QQ图片20220901201640.png' ) label_img = Label(root, image=img_png) label_img.place(x=400 , y=0 , width=350 , height=300 ) content = client.recv(2048 ).decode('utf-8' ) ChatBox = scrolledtext.ScrolledText(root) ChatBox.place(x=5 , y=0 , width=470 , height=300 ) ChatBox.insert('end' ,content) def read_server (c ): while True : content = c.recv(2048 ).decode('utf-8' ) ChatBox.insert('end' , '\n' +content+'\n\n' ) ChatBox.see(tkinter.END) ChatBox.update() threading.Thread(target=read_server, args=(client,)).start() word = StringVar() word.set ('' ) SentBox = Entry(root,width=140 ,textvariable=word) SentBox.place(x=5 ,y=305 ,width=475 ,height=90 ) def sendtext (): content = word.get() if content=='end' : client.close() client.send(content.encode('utf-8' )) word.set ('' ) sendButton = Button(root, text='发 送' , font=('Fangsong' , 18 ), bg='white' , command=sendtext) sendButton.place(x=490 , y=308 , width=150 , height=85 ) root.mainloop() LoginWindow()
(29条消息) Python—多线程编程(一)线程的创建,管理,停止_onesalatree的博客-CSDN博客_python线程开始结束
(29条消息) python GUI 多线程 暂停 恢复 结束_为此残生的博客-CSDN博客
(29条消息) Python多线程的退出控制_Messy…的博客-CSDN博客_python关闭线程的方法
(29条消息) python多线程之 终止子线程_水w的博客-CSDN博客_python 结束线程
实训一阶段2:可靠传输
要求:
了解聊天程序的一般原理;
按照带流量控制的协议改造聊天程序;
编程语言不限;
要能在两台PC上运行。
初级阶段5:可靠传输与流量控制
可靠传输:使用差错检测技术 ,接收方的数据链路层就可以检测出帧在传输过程中是否产生了误码。
如果可靠传输,能够在检测出误码之后,返回一个通知帧,告诉发送方之前传输的帧存在误码,也许可以解决误码重传的问题
数据链路层传输差错:比特差错、分组丢失、分组失序、分组重复
可靠传输 :想方法实现发送端发送什么,接收端就收到什么
计算机网络之流量控制(停止-等待协议1:1、滑动窗口:后退N帧协议GBN、选择重传协议SR)、滑动窗口、可靠传输机制
1.什么是流量控制 ?
流量控制是数据链路层的一种功能,流量控制对数据链路上的帧的发送速率进行控制,以使接收方有足够的缓冲空间来接受每个帧
流量控制的基本方法是由接收方控制发送方发送数据的速率
常见的流量控制方式有两种:停止-等待协议、滑动窗口协议
2.什么是可靠传输机制?
可靠传输机制是为了使数据可以正确稳定的传输和接收而制定的规则。
数据链路层的可靠传输通常使用确认和超时重传两种机制来完成。
确认是一种无数据的控制帧,这种控制帧使得接收方可以让发送方知道哪些内容被正确接收。有些情况下为了提高传输效率,将确认捎带在一个回复帧中,称为捎带确认。
超时重传是指发送方在发送某一个数据帧以后就开始一个计时器,在一定时间内如果没有得到发送的数据帧的确认帧,那么就重新发送该数据帧,直到发送成功为止。
自动重传请求(Auto Repeat reQuest,ARQ),通过接收方请求发送方重传出错的数据帧来恢复出错的帧,是通信中用于处理信道所带来差错的方法之一。
传统自动重传请求分为三种,即停等式(Stop-and-Wait)ARQ、后退N帧(Go-Back-N)ARQ以及选择性重传(Selective Repeat)ARQ。后两种协议是滑动窗口技术与请求重发技术的结合,由于窗口尺寸开到足够大,帧在线路上可以连续地流动,因此又称为连续ARQ协议。
3.什么是滑动窗口机制?
滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。
发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。
不同的滑动窗口协议窗口大小一般不同。
发送方窗口内的序列号代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。
PS:直接看王道考研-计算机网络 3.4
0.6
作用:CRC校验有问题,基础功能实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 import socketimport threadingfrom tkinter import *import tkinter.messagebox from tkinter import scrolledtext server_host = socket.gethostname() server_port = 9999 client = socket.socket() print ('Connecting......' )def LoginWindow (): root = Tk() root.title('一起来聊天 · 登录' ) root.geometry('300x150' ) root.geometry('+500+300' ) nickname = StringVar() root.resizable(0 , 0 ) def Login_in (): name = nickname.get() if not name: tkinter.messagebox.showwarning('Warning' , message='用户名为空!' ) elif len (name) > 10 : tkinter.messagebox.showwarning('Warning' , message='用户名过长!最多为十个字符!' ) else : root.destroy() client.connect((server_host, server_port)) print ('Connecting is successful!' ) client.send(name.encode('utf-8' )) ChatRoom(name) Button(root, text="登录" , command=Login_in, width=8 , height=1 ).place(x=100 , y=90 , width=100 , height=35 ) Label(root, text='请输入昵称' , font=('Fangsong' , 12 )).place(x=10 , y=20 , height=50 , width=80 ) Entry(root, textvariable=nickname, font=('Fangsong' , 11 )).place(x=100 , y=30 , height=30 , width=180 ) root.mainloop() def ChatRoom (nickname ): root = Tk() root.geometry('650x400' ) root.resizable(0 , 0 ) root.geometry('+500+300' ) root.title('一起来聊天 · ' + nickname) img_png = PhotoImage(file='QQ图片20220901201640.png' ) label_img = Label(root, image=img_png) label_img.place(x=400 , y=0 , width=350 , height=300 ) ChatBox = scrolledtext.ScrolledText(root) ChatBox.place(x=5 , y=0 , width=470 , height=300 ) def read_server (c ): while True : content = c.recv(2048 ).decode('utf-8' ) ChatBox.insert('end' , '\n' +content+'\n' ) ChatBox.see(tkinter.END) ChatBox.update() threading.Thread(target=read_server, args=(client,)).start() word = StringVar() word.set ('' ) SentBox = Entry(root,width=140 ,textvariable=word) SentBox.place(x=5 ,y=305 ,width=475 ,height=90 ) def sendtext (): content = word.get() if content=='end' : client.close() client.send(content.encode('utf-8' )) word.set ('' ) sendButton = Button(root, text='发 送' , font=('Fangsong' , 18 ), bg='white' , command=sendtext) sendButton.place(x=490 , y=308 , width=150 , height=85 ) root.mainloop() LoginWindow()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 import socketimport threadingimport timehost = socket.gethostname() port = 9999 SocketList = [] TextList = [] Nickname = [] cnt = 0 print (host)server = socket.socket() server.bind((host,port)) server.listen() print ('服务器准备就绪!' )def CRC (crc,poly='11001' ): test_crc = int (crc,16 ) poly_crc8 = int (poly,16 ) for bit in range (12 ): if test_crc&0x800 != 0 : test_crc <<= 1 test_crc ^= poly_crc8 else : test_crc <<= 1 print (test_crc) return hex (test_crc) def read_client (s,nickname ): try : return s.recv(2048 ).decode('utf-8' ) except : print (nickname + '已下线!' ) SocketList.remove(s) Nickname.remove(nickname) for sock in SocketList: sock.send(('系统消息:' + nickname + '已下线!' ).encode('utf-8' )) def send_client (s,nickname ): try : while True : content = read_client(s,nickname) if content is None : break else : TextList.append(nickname + ': ' + content) for sock in SocketList: sock.send((nickname + ': ' + content).encode('utf-8' )) data = CRC(content) for sock in SocketList: sock.send(('Teacher: ' + data).encode('utf-8' )) except Exception as e: print ('广播未成功!' ) QianYan = ['你好呀!今天我们一起来学习SW。' , '可靠传输机制是为了使数据可以正确稳定的传输和接收而制定的规则。' , '流量控制是数据链路层的一种功能,流量控制对数据链路上的帧的发送速率进行控制,以使接收方有足够的缓冲空间来接受每个帧。' , '流量控制的基本方法是由接收方控制发送方发送数据的速率。' , '常见的流量控制方式有两种:`停止-等待协议、滑动窗口协议' , '那么,让我们开始体验停止-等待协议SW的魅力吧!' , '\n\n请输入十六进制数据' ] while True : client,addr = server.accept() SocketList.append(client) nickname = client.recv(2048 ).decode('utf-8' ) if nickname in Nickname: i = 1 while True : if nickname+str (i) in Nickname: i = i+1 else : nickname = nickname + str (i) break Nickname.append(nickname) print (nickname + '已加入!' ) for sock in SocketList: for i in QianYan: sock.send(('Teacher: ' + i).encode('utf-8' )) time.sleep(1 ) cnt = cnt + 1 threading.Thread(target=send_client, args=(client,nickname,)).start()
0.65
作用:早上灵光一现,以为CRC是取模了……
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 import socketimport threadingimport timehost = socket.gethostname() port = 9999 SocketList = [] TextList = [] Nickname = [] cnt = 0 print (host)server = socket.socket() server.bind((host,port)) server.listen() print ('服务器准备就绪!' )def DEC (data ): s = data d = 0 while s: d = d*2 + (ord (s[0 ]) -ord ('0' )) s = s[1 :] return d def CRC (crc,poly='11001' ): p = DEC(poly) c = DEC(crc+'0000' ) print (p,c) res = c%p return res def read_client (s,nickname ): try : return s.recv(2048 ).decode('utf-8' ) except : print (nickname + '已下线!' ) SocketList.remove(s) Nickname.remove(nickname) for sock in SocketList: sock.send(('系统消息:' + nickname + '已下线!' ).encode('utf-8' )) def send_client (s,nickname ): try : while True : content = read_client(s,nickname) if content is None : break else : TextList.append(nickname + ': ' + content) for sock in SocketList: sock.send((nickname + ': ' + content).encode('utf-8' )) data = CRC(content) if data==0 : word = '发送帧没问题。' else : word = '发送帧有问题。' for sock in SocketList: sock.send(('Teacher: ' + word).encode('utf-8' )) except Exception as e: print ('广播未成功!' ) QianYan = ['你好呀!今天我们一起来学习SW。' , '可靠传输机制是为了使数据可以正确稳定的传输和接收而制定的规则。' , '流量控制是数据链路层的一种功能,流量控制对数据链路上的帧的发送速率进行控制,以使接收方有足够的缓冲空间来接受每个帧。' , '流量控制的基本方法是由接收方控制发送方发送数据的速率。' , '常见的流量控制方式有两种:`停止-等待协议、滑动窗口协议' , '那么,让我们开始体验停止-等待协议SW的魅力吧!' , '\n\n请输入十六进制数据' ] while True : client,addr = server.accept() SocketList.append(client) nickname = client.recv(2048 ).decode('utf-8' ) if nickname in Nickname: i = 1 while True : if nickname+str (i) in Nickname: i = i+1 else : nickname = nickname + str (i) break Nickname.append(nickname) print (nickname + '已加入!' ) for sock in SocketList: for i in QianYan: sock.send(('Teacher: ' + i).encode('utf-8' )) time.sleep(1 ) cnt = cnt + 1 threading.Thread(target=send_client, args=(client,nickname,)).start()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 import socketimport threadingfrom tkinter import *import tkinter.messagebox from tkinter import scrolledtext server_host = socket.gethostname() server_port = 9999 client = socket.socket() print ('Connecting......' )def LoginWindow (): root = Tk() root.title('一起来聊天 · 登录' ) root.geometry('300x150' ) root.geometry('+500+300' ) nickname = StringVar() root.resizable(0 , 0 ) def Login_in (): name = nickname.get() if not name: tkinter.messagebox.showwarning('Warning' , message='用户名为空!' ) elif len (name) > 10 : tkinter.messagebox.showwarning('Warning' , message='用户名过长!最多为十个字符!' ) else : root.destroy() client.connect((server_host, server_port)) print ('Connecting is successful!' ) client.send(name.encode('utf-8' )) ChatRoom(name) Button(root, text="登录" , command=Login_in, width=8 , height=1 ).place(x=100 , y=90 , width=100 , height=35 ) Label(root, text='请输入昵称' , font=('Fangsong' , 12 )).place(x=10 , y=20 , height=50 , width=80 ) Entry(root, textvariable=nickname, font=('Fangsong' , 11 )).place(x=100 , y=30 , height=30 , width=180 ) root.mainloop() def ChatRoom (nickname ): root = Tk() root.geometry('650x400' ) root.resizable(0 , 0 ) root.geometry('+500+300' ) root.title('一起来聊天 · ' + nickname) img_png = PhotoImage(file='QQ图片20220901201640.png' ) label_img = Label(root, image=img_png) label_img.place(x=400 , y=0 , width=350 , height=300 ) ChatBox = scrolledtext.ScrolledText(root) ChatBox.place(x=5 , y=0 , width=470 , height=300 ) def read_server (c ): while True : content = c.recv(2048 ).decode('utf-8' ) ChatBox.insert('end' , '\n' +content+'\n' ) ChatBox.see(tkinter.END) ChatBox.update() threading.Thread(target=read_server, args=(client,)).start() word = StringVar() word.set ('' ) SentBox = Entry(root,width=140 ,textvariable=word) SentBox.place(x=5 ,y=305 ,width=475 ,height=90 ) def sendtext (): content = word.get() if content=='end' : client.close() client.send(content.encode('utf-8' )) word.set ('' ) sendButton = Button(root, text='发 送' , font=('Fangsong' , 18 ), bg='white' , command=sendtext) sendButton.place(x=490 , y=308 , width=150 , height=85 ) root.mainloop() LoginWindow()
0.7
作用:拿的网上的CRC但感觉还是错的……
crc原理Python - Search (bing.com)
https://blog.csdn.net/smallfox233/article/details/111242813
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 import socketimport threadingimport timehost = socket.gethostname() port = 9999 SocketList = [] TextList = [] Nickname = [] cnt = 0 print (host)server = socket.socket() server.bind((host,port)) server.listen() print ('服务器准备就绪!' )def TurnBin (expression ): '''将生成多项式转换为二进制字符串输出''' expression = expression.upper() lis = list (expression.split("+" )) string = lis[-1 ] del lis[-1 ] lis = lis[::-1 ] for i in range (len (lis)): if len (string) == int (lis[i][1 ]): string += "1" else : for j in range (int (lis[i][1 ]) - len (string)): string += "0" string += "1" return string[::-1 ] def XOR (string1, string2 ): '''将两个二进制串进行异或操作,不同为1''' result = "" if len (string1) < len (string2): for i in range (len (string2) - len (string1)): string1 = "0" + string1 if len (string1) > len (string2): for i in range (len (string1) - len (string2)): string2 = "0" + string2 for i in range (len (string1)): if string1[i] != string2[i]: result += "1" else : result += "0" for i in range (len (result)): if result[i] == "1" : return result[i::] return result def CRC (string, expression ): '''产生CRC校验码''' crc = "" bin_expression = TurnBin(expression) for i in range (len (bin_expression) - 1 ): string += "0" for i in range (len (string)): crc += string[i] if len (crc) == len (bin_expression): crc = XOR(crc, bin_expression) if len (crc) < len (bin_expression) - 1 : for i in range (len (bin_expression) - len (crc)): crc = "0" + crc if len (crc) > len (bin_expression) - 1 : crc = crc[len (crc) - len (bin_expression) + 1 ::] return crc def CheckCRC (string, expression='x4+x3+1' ): bin_expression = TurnBin(expression) right_crc = string[len (string) - len (bin_expression) + 1 ::] crc = CRC(string[:len (string) - len (bin_expression) + 1 :], expression) if right_crc == crc: word ="数据传输过程正常..\n检测出的校验码:" +str (crc)+'\n数据尾部校验码:' +str (right_crc) else : word ="数据传输过程出错..\n检测出的校验码:" +str (crc)+'\n数据尾部校验码:' +str (right_crc) for sock in SocketList: sock.send(('Teacher: ' + word).encode('utf-8' )) def read_client (s,nickname ): try : return s.recv(2048 ).decode('utf-8' ) except : print (nickname + '已下线!' ) SocketList.remove(s) Nickname.remove(nickname) for sock in SocketList: sock.send(('系统消息:' + nickname + '已下线!' ).encode('utf-8' )) def send_client (s,nickname ): try : while True : content = read_client(s,nickname) if content is None : break else : TextList.append(nickname + ': ' + content) for sock in SocketList: sock.send((nickname + ': ' + content).encode('utf-8' )) CheckCRC(content) except Exception as e: print ('广播未成功!' ) QianYan = [ '你好呀!今天我们一起来学习SW。' , '可靠传输机制是为了使数据可以正确稳定的传输和接收而制定的规则。' , '流量控制是数据链路层的一种功能,流量控制对数据链路上的帧的发送速率进行控制,以使接收方有足够的缓冲空间来接受每个帧。' , '流量控制的基本方法是由接收方控制发送方发送数据的速率。' , '常见的流量控制方式有两种:`停止-等待协议、滑动窗口协议' , '那么,让我们开始体验停止-等待协议SW的魅力吧!' , '\n\n请输入高于4位的二进制数据' ] while True : client,addr = server.accept() SocketList.append(client) nickname = client.recv(2048 ).decode('utf-8' ) if nickname in Nickname: i = 1 while True : if nickname+str (i) in Nickname: i = i+1 else : nickname = nickname + str (i) break Nickname.append(nickname) print (nickname + '已加入!' ) for sock in SocketList: for i in QianYan: sock.send(('Teacher: ' + i).encode('utf-8' )) time.sleep(1 ) cnt = cnt + 1 threading.Thread(target=send_client, args=(client,nickname,)).start()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 import socketimport threadingfrom tkinter import *import tkinter.messagebox from tkinter import scrolledtext server_host = socket.gethostname() server_port = 9999 client = socket.socket() print ('Connecting......' )def LoginWindow (): root = Tk() root.title('一起来聊天 · 登录' ) root.geometry('300x150' ) root.geometry('+500+300' ) nickname = StringVar() root.resizable(0 , 0 ) def Login_in (): name = nickname.get() if not name: tkinter.messagebox.showwarning('Warning' , message='用户名为空!' ) elif len (name) > 10 : tkinter.messagebox.showwarning('Warning' , message='用户名过长!最多为十个字符!' ) else : root.destroy() client.connect((server_host, server_port)) print ('Connecting is successful!' ) client.send(name.encode('utf-8' )) ChatRoom(name) Button(root, text="登录" , command=Login_in, width=8 , height=1 ).place(x=100 , y=90 , width=100 , height=35 ) Label(root, text='请输入昵称' , font=('Fangsong' , 12 )).place(x=10 , y=20 , height=50 , width=80 ) Entry(root, textvariable=nickname, font=('Fangsong' , 11 )).place(x=100 , y=30 , height=30 , width=180 ) root.mainloop() def ChatRoom (nickname ): root = Tk() root.geometry('650x400' ) root.resizable(0 , 0 ) root.geometry('+500+300' ) root.title('一起来聊天 · ' + nickname) img_png = PhotoImage(file='QQ图片20220901201640.png' ) label_img = Label(root, image=img_png) label_img.place(x=400 , y=0 , width=350 , height=300 ) ChatBox = scrolledtext.ScrolledText(root) ChatBox.place(x=5 , y=0 , width=470 , height=300 ) def read_server (c ): while True : content = c.recv(2048 ).decode('utf-8' ) ChatBox.insert('end' , '\n' +content+'\n' ) ChatBox.see(tkinter.END) ChatBox.update() threading.Thread(target=read_server, args=(client,)).start() word = StringVar() word.set ('' ) SentBox = Entry(root,width=140 ,textvariable=word) SentBox.place(x=5 ,y=305 ,width=475 ,height=90 ) def sendtext (): content = word.get() if content=='end' : client.close() client.send(content.encode('utf-8' )) word.set ('' ) sendButton = Button(root, text='发 送' , font=('Fangsong' , 18 ), bg='white' , command=sendtext) sendButton.place(x=490 , y=308 , width=150 , height=85 ) root.mainloop() LoginWindow()
实训二阶段
(29条消息) Cisco Packet Tracer安装详解_@Protinx的博客-CSDN博客_cisco packet tracer
思科模拟器 Cisco Packet Tracer 是一个功能强大的网络仿真程序,允许学生实验与网络行为。但是这个软件是纯软件模拟,和真实的环境有差距,命令也不全。适合新手教程教学使用。
(29条消息) 思科Packet Tracer基础使用教程_冰镇阔落的博客-CSDN博客_cisco packet tracer教程
(29条消息) Cisco Packet Tracer软件介绍与使用方法_发光吖的博客-CSDN博客_packet tracer
一般选择高型号的路由器(可支持的命令比较多),在Packet Tracer 5.3里面推荐选择2811系列路由器。
交换机也选择高型号的,推荐选择2960系列。(注:2xxx系列为二层交换机,3xxx系列为三层交换机。两者交换功能相同,但三层交换机多了路由功能,在一些情况下三层交换机可以代替路由器,但不能完全替代路由器)
交换机(Switch)意为“开关 ”是一种用于电(光)信号转发的网络设备 。它可以为接入交换机的任意两个网络节点 提供独享的电信号通路。
一般情况下选择(自动线)即可,或选择(直通线)。若方案要求选择专线,则需要选择(专线)。方案中线路大多为直通线(即以太网线),少数会有专线要求。
点击一下所要使用的线,然后点击需要连线的设备接口,从一个设备接口连线至另一个设备接口。(注:自动线不需要选择接口,其他两种线需要手动选择接口。直通线选择Fast开头的接口,专线选择Serial开头的接口)
注:自动线连好为虚线;直通线连好为实线。
交换机是用来连接局域网的,路由器是用来连接互联网的(也可以连接多个局域网)
各线缆两端有不同颜色的圆点,它们分别表示什么样的含义呢?
链路圆点的状态
含义
亮绿色
物理连接准备就绪,还没有Line Protocol status 的指示
闪烁的绿色
连接激活
红色
物理连接不通,没有信号
黄色
交换机端口处于"阻塞"状态
路由器和交换机区别
路由器:寻址,转发(依靠 IP 地址),交换机:过滤,转发(依靠 MAC 地址)
交换机用于连接局域网,数据包在局域网内网的数据转发,路由器用于连接局域网和外网,数据包可以在不同局域网转发。
交换机工作于TCP/IP协议的最后一层数据链路层(物理层),路由器工作于网络层
交换机负责具体的数据包传输,路由器不负责包的实际传输,路由器只封装好要传输的数据包,然后交给交换机去传输(不一定是交换机,可能是其他传输技术),用java比喻大概简单理解为路由器是抽象类,定义好传输的数据包格式,交换机是具体实现类,也可以有其他实现类
交换机没有MAC地址和IP地址,路由器有MAC地址和IP地址(指纯碎的交换机和路由器,三层交换机是可以有IP地址的,路由器也有内置交换机功能的)
原文链接:https://blog.csdn.net/qq_21187515/article/details/119416934
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Router>enable Router (Router>en) 在用户模式下输入enable即可进入特权模式。第二级别模式,可以对设备进行所有的查看、测试及简单的配置。 Router Enter configuration commands, one per line. End with CNTL/Z. Router(config) (Router 在特权模式下,输入configure terminal即可进入配置模式。第三级别模式,可以对设备进行管理配置。 Router(config) Router(config-if ) (Router(config) 其他配置模式Router(config-???) Router(config-if ) (Router(config-if ) 配置ip地址 R2(config-if ) (Router(config-if ) 激活接口 (Router(config-if ) Building configuration... Router(config-if ) C 192.168 .1 .0 /24 is directly connected, FastEthernet0/0 //路由表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 路由器配置 Router>en Router Router Router(config) Router(config-if ) Router(config-if ) Router(config-if ) Router(config-if ) Router(config-if ) Router(config-if ) Router(config-if ) Codes: C - connected, S - static, I - IGRP, R - RIP, M - mobile, B - BGP D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1 , N2 - OSPF NSSA external type 2 E1 - OSPF external type 1 , E2 - OSPF external type 2 , E - EGP i - IS-IS, L1 - IS-IS level-1 , L2 - IS-IS level-2 , ia - IS-IS inter area * - candidate default, U - per-user static route, o - ODR P - periodic downloaded static route Gateway of last resort is not set C 192.168 .1 .0 /24 is directly connected, FastEthernet0/0 //路由表 C 192.168 .2 .0 /24 is directly connected, FastEthernet0/1
(29条消息) 交换机实验、VLAN创建_Air_Echo的博客-CSDN博客_创建vlan
打开**【PC中 >> Desktop >> Commond prompt】**
pc0上 ping 192.168.20.1 (PC1)的ip地址
(29条消息) Cisco Packet Tracer 命令大全 【思科交换机模拟器命令大全】_zhangbw~的博客-CSDN博客_cisco packet tracer命令行
(29条消息) Cisco Packet Tracer—VLAN配置详解_HOPEAMOR的博客-CSDN博客
(29条消息) cisco交换机 配置一组端口,interface range_weixin_34194317的博客-CSDN博客
当使用interface range 命令时有如下的规则:
有效的组范围:
vlan从1 到4094
fastethernet 槽位/{first port} - {last port}, 槽位为0
gigabitethernet槽位/{first port} - {last port},槽位为0
port-channel port-channel-number - port-channel-number, port-channel号从1到64
端口号之间需要加入空格,如:interface range fastethernet 0/1 – 5 是有效的,而interface range fastethernet 0/1-5 是无效的.
interface range 命令只能配置已经存在的interface vlan
所有在同一组的端口必须是相同类别的。
见以下例子:
Switch# configure terminal
Switch(config)# interface range fastethernet0/1 - 5
#switch trunk encapsulation dot1q
IEEE 802.1Q协议 ,是vlan的一种封装方式,是公有协议。 还有一种trunk协议,是ISL,也是vlan的一种封装方式,不过这是Cisco思科私有协议,其他厂商不能用。
#switchport trunk 是配置允许通过的vlan;
switchport mode trunk是将端口配置成trunk模式;
mode trunk //端口模式为trunk
switchport trunk encapsulation dot1q //trunk协议封装为dot1q
dot1q就是 IEEE 802.1Q协议,是vlan的一种封装方式,是公有协议。
还有一种trunk协议,是ISL,也是vlan的一种封装方式,不过这是Cisco思科私有协议,其他厂商不能用。
实训1:局域网分层结构
1 2 3 4 5 1.基本任务 三层交换上实现VLAN间路由; 两层交换机上划分VLAN; VLAN数目不少于2个; 自行规划IP地址
技术原理
三层交换机具备网络层的功能,实现 VLAN 相互访问的原理是:利用三层交换机的路由功能,通过识别数据包的 IP 地址,查找路由表进行选路转发,三层交换机利用直连路由可以实现不同 VLAN 之间的相互访问。
三层交换机给接口配置 IP 地址。采用 SVI(交换虚拟接口)的方式实现 VLAN 间互连。SVI 是指为交换机中的VLAN 创建虚拟接口,并且配置 IP 地址 。
Tag VLAN是基于交换机端口的一种类型,主要用于使交换机的相同Vlan内的主机之间 可以直接访问,同时对于不同Vlan的主机进行隔离。
trunk主要用在连接其它交换机 ,以便在线路上承载多个vlanWLAN是Wireless Local Area Network的简称,指应用无线通信技术将计算机设备互联起来,构成可以互相通信和实现资源共享的网络体系。
802.1x协议是WLAN第二代的认证技术,它是基于客户端-服务器(Client-Server)结构的访问控制和认证协议。它可以限制未经授权的用户/设备通过接入端口(Access Port)访问LAN/WLAN。
DOT1Q是提供VLAN识别和服务质量(QoS)级别的IEEE标准。电气和电子工程师协会(IEEE,全称是Institute of Electrical and Electronics Engineers)是一个美国的电子技术与信息科学工程师的协会,是世界上最大的非营利性专业技术学会。
ip routing 启用IP路由功能no ip routing 关闭IP路由功能
二层交换机与三层交换机区别
我们习惯说,在二层网络环境中相同vlan之间可以通信,不同vlan之间不可以通信,如果想通信必须借助三层设备 ,所以说三层交换机必须要做的事情是路由转发 ,但是二、三层交换机具体有什么区别呢?
二层交换机工作于OSI模型的第2层(数据链路层),故而称为二层交换机。二层交换技术发展比较成熟,二层交换机属数据链路层设备,可以识别数据包中的MAC地址信息,根据MAC地址进行转发 ,并将这些MAC地址与对应的端口记录在自己内部的一个地址表中。具体的工作流程如下:
(1) 当交换机从某个端口收到一个数据包,它先读取包头中的源MAC地址,这样它就知道源MAC地址的机器是连在哪个端口上的;
(2) 再去读取包头中的目的MAC地址,并在地址表中查找相应的端口;
(3) 如表中有与这目的MAC地址对应的端口,把数据包直接复制到这端口上;
(4) 如表中找不到相应的端口则把数据包广播到所有端口上,当目的机器对源机器回应时,交换机又可以学习一目的MAC地址与哪个端口对应,在下次传送数据时就不再需要对所有端口进行广播了。
不断的循环这个过程,对于全网的MAC地址信息都可以学习到,二层交换机就是这样建立和维护它自己的地址表。二层交换技术从网桥发展到VLAN(虚拟局域网),在局域网建设和改造中得到了广泛的应用。第二层交换技术是工作在OSI七层网络模型中的第二层,即数据链路层。它按照所接收到数据包的目的MAC地址来进行转发,对于网络层或者高层协议来说是透明的。它不处理网络层的IP地址 ,不处理高层协议的诸如TCP、UDP的端口地址,它只需要数据包的物理地址即MAC地址,数据交换是靠硬件来实现的,其速度相当快,这是二层交换的一个显著的优点 。但是,它不能处理不同IP子网之间的数据交换 。
传统的路由器可以处理大量的跨越IP子网的数据包,但是它的转发效率比二层低,因此要想利用二层转发效率高这一优点,又要处理三层IP数据包,三层交换技术就诞生了。
三层交换(也称多层交换技术,或IP交换技术)是相对于传统交换概念而提出的。众所周知,传统的交换技术是在OSI网络标准模型中的第二层——数据链路层进行操作的,而三层交换技术是在网络模型中的第三层实现了数据包的高速转发。简单地说,**三层交换技术就是:二层交换技术+三层转发技术。**三层交换机就是具有部分路由器功能的交换机。三层交换机的最重要目的是加快大型局域网内部的数据交换,所具有的路由功能也是为这目的服务的,能够做到一次路由,多次转发。对于数据包转发等规律性的过程由硬件高速实现,而像路由信息更新、路由表维护、路由计算、路由确定等功能,由软件实现。三层交换技术就是二层交换技术+三层转发技术。三层交换技术的出现,解决了局域网中网段划分之后,网段中子网必须依赖路由器进行管理的局面,解决了传统路由器低速、复杂所造成的网络瓶颈问题。
实验步骤
1)在二层交换机上配置 VLAN2、VLAN3,分别将端口 2、端口 3 划分给 VLAN2、VLAN3。
(2)将二层交换机与三层交换机相连的端口 fa 0/1 都定义为 tag Vlan 模式。
(3)在三层交换机上配置 VLAN2、VLAN3,此时验证二层交换机 VLAN2、VLAN3下的主机之间不能相互通信。
(4)设置三层交换机 VLAN 间的通信,创建 VLAN2,VLAN3 的虚接口,并配置虚接口 VLAN2、VLAN3 的 IP 地址。
(5)查看三层交换机路由表。
(6)将二层交换机 VLAN2、VLAN3 下的主机默认网关分别设置为相应虚拟接口的 IP 地址。
(7)验证二层交换机 VLAN2,VALN3 下的主机之间可以相互通信。
switchport access vlan 3
语法:
switchport access vlan vlan-id
no switchport access vlan
该命令把一个Access接口指派给一个VLAN 。使用 no 选项可以把接口指派到缺省的VLAN中。
缺省值:接口缺省的VLAN是 VLAN 1。
命令模式:接口配置模式
适用接口:2层物理接口。
说明:如果指定的VLAN不存在,则系统会创建这个VLAN,并把接口设置为该VLAN的成员。如果指定的VLAN已经存在,则把接口添加到该VLAN中。如果接口是一个Trunk口,该操作没有任何作用。可以用 show vlan 命令查看VLAN信息。
范例:
Ruijie(config)# interface f0/1
Ruijie(config)# switchport
Ruijie(config-if)# switchport access vlan 10
本例把 FastEthernat 0/1 口设置为2层口,并把它加入到 VLAN 10 中。
#switchport mode trunk
语法:
switchport mode { access | trunk }
no switchport mode
该命令**指定一个2层接口的模式,可以把接口指定为 access 接口或者 trunk 接口。**使用 no 选项可以把接口模式恢复为缺省值。
缺省值:接口的缺省模式是 access。
命令模式:接口配置模式
适用接口:2层物理接口、2层Aggregateport接口。
说明:如果一个接口的模式是 access,则该接口只能成为一个VLAN的成员,可以使用 switchport access vlan 命令把它指定给一个VLAN;如果一个接口的模式是 trunk,则该接口可以是多个VLAN的成员,可以用 switchport trunk 命令定义许可VLAN列表决定它所在的VLAN。
范例:
Ruijie(config)# interface f0/1
Ruijie(config-if)# switchport mode trunk
本例把 FastEthernat 0/1 口设置为 Trunk 接口。
(29条消息) Switchport详细用法_天地良心的博客-CSDN博客
三个空的的口令分别是:
interface e0 //根据图示这个是E0口。
192.168.2.1 255.255.255.0 //R1的S0接口的IP地址和子网掩码。
s0 //这个是送出接口
ip routing 是用在三层交换机上打开路由功能,默认是关闭的 ,ip router ospf 是在路由器上启用ospf等路由协议,ospf后面还要加个进程号,范围是0-65535,只具有本地意义
ip routing启用IP路由功能:
配置三层交换机启动路由功能:ip routing 。
配置VLAN IP地址:
interface vlan vlan-id
Ip address ip-address subnet-mask
No shutdown
配置接口为三层模式:
no switchport
配置DHCP中继转发:
int vlan vlan-i
Ip helper-address Dhcpserver-address
配置静态路由:
ip route targetnet-address netmask nexthop-address
配置RIP协议:
router rip
查看FIB表:
show ip cef
查看邻接关系表:
show adjacency detail
查看路由表:
show ip route
PC1 IP: 192.168.1.2 Submark: 255.255.255.0 Gateway: 192.168.1.1
PC2 IP: 192.168.2.2 Submark: 255.255.255.0 Gateway: 192.168.2.1
PC3 IP: 192.168.1.3 Submark: 255.255.255.0 Gateway: 192.168.1.1
二层交换机
Switch>en
Switch#conf t
Enter configuration commands, one per line. End with CNTL/Z.
Switch(config)#vlan 2
Switch(config-vlan)#exit
Switch(config)#vlan 3
Switch(config-vlan)#int fa 0/2
Switch(config-if)#switchport access vlan 2
Switch(config-if)#int fa 0/3
Switch(config-if)#switchport access vlan 3
Switch(config-if)#int fa 0/1
Switch(config-if)#switchport mode trunk
%LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/1, changed state to down
%LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/1, changed state to up
Switch(config-if)#end
Switch#
%SYS-5-CONFIG_I: Configured from console by console
Switch#show vlan
VLAN Name Status Ports
1 default active Fa0/4, Fa0/5, Fa0/6, Fa0/7
Fa0/8, Fa0/9, Fa0/10, Fa0/11
Fa0/12, Fa0/13, Fa0/14, Fa0/15
Fa0/16, Fa0/17, Fa0/18, Fa0/19
Fa0/20, Fa0/21, Fa0/22, Fa0/23
Fa0/24, Gig1/1, Gig1/2
2 VLAN0002 active Fa0/2
3 VLAN0003 active Fa0/3
1002 fddi-default act/unsup
1003 token-ring-default act/unsup
1004 fddinet-default act/unsup
1005 trnet-default act/unsup
VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2
1 enet 100001 1500 - - - - - 0 0
2 enet 100002 1500 - - - - - 0 0
3 enet 100003 1500 - - - - - 0 0
1002 fddi 101002 1500 - - - - - 0 0
–More–
三层交换机
Switch>en
Switch#conf t
Enter configuration commands, one per line. End with CNTL/Z.
Switch(config)#vlan 2
Switch(config-vlan)#exit
Switch(config)#vlan 3
Switch(config-vlan)#exit
Switch(config)#int fa 0/1
Switch(config-if)#switchport trunk encapsulation dot1q
Switch(config-if)#switchport mode trunk
Switch(config-if)#switchport trunk allowed vlan 2,3
Switch(config-if)#exit
Switch(config)#int fa 0/2
Switch(config-if)#switchport access vlan 2
Switch(config-if)#exit
Switch(config)#int vlan 2
%LINK-5-CHANGED: Interface Vlan2, changed state to up
%LINEPROTO-5-UPDOWN: Line protocol on Interface Vlan2, changed state to up
Switch(config-if)#ip address 192.168.1.1 255.255.255.0
Switch(config-if)#no shutdown
Switch(config-if)#exit
Switch(config)#int vlan 3
%LINK-5-CHANGED: Interface Vlan3, changed state to up
%LINEPROTO-5-UPDOWN: Line protocol on Interface Vlan3, changed state to up
Switch(config-if)#ip address 192.168.2.1 255.255.255.0
Switch(config-if)#no shutdown
Switch(config-if)#exit
Switch(config)#ip routing
Switch(config)#exit
Switch#
%SYS-5-CONFIG_I: Configured from console by console
Switch#show ip route
Codes: C - connected, S - static, I - IGRP, R - RIP, M - mobile, B - BGP
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP
i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
candidate default, U - per-user static route, o - ODR
P - periodic downloaded static route
Gateway of last resort is not set
C 192.168.1.0/24 is directly connected, Vlan2
C 192.168.2.0/24 is directly connected, Vlan3
Switch#show vlan
VLAN Name Status Ports
1 default active Fa0/3, Fa0/4, Fa0/5, Fa0/6
Fa0/7, Fa0/8, Fa0/9, Fa0/10
Fa0/11, Fa0/12, Fa0/13, Fa0/14
Fa0/15, Fa0/16, Fa0/17, Fa0/18
Fa0/19, Fa0/20, Fa0/21, Fa0/22
Fa0/23, Fa0/24, Gig0/1, Gig0/2
2 VLAN0002 active Fa0/2
3 VLAN0003 active
1002 fddi-default act/unsup
1003 token-ring-default act/unsup
1004 fddinet-default act/unsup
1005 trnet-default act/unsup
VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2
1 enet 100001 1500 - - - - - 0 0
2 enet 100002 1500 - - - - - 0 0
3 enet 100003 1500 - - - - - 0 0
1002 fddi 101002 1500 - - - - - 0 0
–More–
PC1 分别 ping PC2 和 PC3
PC>ipconfig IP
Address…: 192.168.1.2
Subnet Mask…: 255.255.255.0
Default Gateway…: 192.168.1.1
PC>ping 192.168.2.2
Pinging 192.168.2.2 with 32 bytes of data:
Request timed out.
Reply from 192.168.2.2: bytes=32 time=25ms TTL=127
Reply from 192.168.2.2: bytes=32 time=20ms TTL=127
Reply from 192.168.2.2: bytes=32 time=20ms TTL=127
Ping statistics for 192.168.2.2:
Packets: Sent = 4, Received = 3, Lost = 1 (25% loss), Approximate round trip times in milli-seconds: Minimum = 20ms, Maximum = 25ms, Average = 21ms
1 2 3 2.拓展任务 使用VTP管理交换机 启用快速生成树,采用线路冗余的方式增加可靠性。
https://www.cnblogs.com/zoulongbin/p/9047390.html
VTP的工作原理
VTP:虚拟局域网中继协议,VTP是一种消息协议,它使用第二层帧,在交换机之间传递VLAN信息 ,被称为VTP通告。有了VTP通告就可以再一台交换机上集中修改VLAN配置,所做的修改会被自动传播到网络中的其他交换机,从而实现VLAN配置的一致性。
VTP域:也称为VLAN管理域,由一个以上共享VTP域名相连接的交换机组成。也就是说,VTP域是一组VTP域名相同并通过中继链路互相连接的交换机。使用VTP首先需要建立一个VTP管理域,在同一管理域中的交换机共享他们的VLAN信息,并且一个交换机只能参加一个VTP管理域 。
配置VTP域的要求如下:
1、域内的每台交换机都必须使用相同的VTP域名。
2、交换机必须是相邻的,即相邻的交换机并具有相同的域名。
3、交换机之前必须配置中继链路(也就是Trunk)。
它不通告自己的VLAN配置信息,对收到的VTP通告只转发而不会学习与更改自己的VLAN信息。
VTP的模式
1、服务器模式:充当VTP服务器模式的交换机负责它所在域中VLAN信息的管理工作。VTP服务器可以创建、删除或修改VLAN,并向外发送VTP通告,同时,VTP服务器也会学习域名相同的VTP通告信息。
2、客户机模式:处于VTP客户机模式的交换机不允许管理创建,删除或修改VLAN。它们监听本域中其他交换机的VTP通告,并相应修改它们自己的VTP配置。
3、透明模式:VTP透明模式中的交换机不参与VTP。当交换机处于透明模式时,它可以创建,删除或修改本地的VLAN信息,但
VTP通告
使用VTP时,加入VTP域的每台交换机在其中继端口上通告如下信息:
1、管理域 (即VTP的域名信息)
2、版本号 (使用VTP的版本号,只要校验服务器和客户机模式的版本是否一致)
3、配置修改编号 (默认为0,当修改VTP域的配置之后,此编号会加1)
4、它所知道的VLAN (即VTP中的所有VLAN)
5、每个VLAN的某些参数 (vlan的相关信息)
注意:当一台修改编号高于此VTP域中的修改编号的交换机加入此VTP域时,此交换机的中的VLAN配置会覆盖所有VTP域中的VLAN配置,所以将交换机加入VTP域时要格外小心。我们可以将交换机的VTP模式改为透明模式,再改回服务器模式或交换机模式,或者是将交换机的域名更改一下在改回来,就可以将交换机的修改编号初始为0。
VTP修剪
VTP修剪是VTP的一个功能,它能减少中继链路上不必要的广播流量。
配置VTP实例
在配置VTP之前,我们需要将VTP服务器和VTP客户机之间的链路设置为中继链路 。
列如:将Switch1和Switch2的24号端口设置为trunk中继链路。
Switch1(config)#int f0/24
Switch1(config)#switchport mode trunk
Switch1(config)#no sh
Switch2(config)#int f0/24
Switch2(config)#switchport mode trunk
Switch2(config)#no sh
配置VTP服务器模式
列如:将Switch1配置为VTP服务器,域名为test,秘密为123,配置VTP修剪。
Switch1#config terminal
Switch1(config)#vtp domain test
Switch1(config)#vtp mode server
SWitch1(config)#vtp passwd 123
Switch1(config)#vtp pruning
配置VTP客户机模式
列如:将Switch2配置为VTP客户机,域名和密码必须和服务器器一致,否则将不匹配。
Switch2#config terminal
Switch2(config)#vtp domain test
Switch2(config)#vtp mode client
SWitch2(config)#vtp passwd 123
Switch2(config)#vtp pruning
此时VTP服务器和VTP客户端就配置完成了,现在只需要在VTP服务器端创建VLAN,VTP客户端就可以自动学习到服务器端创建的VLAN,而不需要自己创建VLAN,但是注意,虽然VTP客户端可是自动学习VLAN,但是将端口加入VLAN的动作是不可以学习的,所以在客户端需要手动将端口添加到相应的VLAN中。
Unable to perform trunk negotiation on port Fa0/23 because of VTP domain mismatch这句话是什么意思??是不能开启trunk在f0/23上!!因为VTP的域名错了!!你VTP配置的时候是不是名字有问题??要就是配置一个!!要就是两边一样的!!不要两边不一样的!
实训2 多域OSPF
1 2 3 4 要求: 配置多域OSPF; Loopback口相当于PC; 基本配置内容自主网络搜索。
OSPF多用于大型IPv4网络,是基于链路状态的路由协议,与基于距离矢量的路由协议相比具有更快的收敛速度,支撑的网络规模也更大。
OSPF(Open Shortest Path First)是IETF组织开发的一个基于链路状态的内部网关协议。目前针对IPv4协议使用的是OSPF Version 2(RFC2328)。OSPF是不属于任何一个厂商或组织私有的路由协议,使用Dijkstra的最短路径(SPF)算法计算路由。在OSPF中引入了区域的概念,有效的减少了路由选择协议对路由器CPU和内存的占用,同时也降低了路由选择协议的通信量,使得构建大型层次化网络成为可能
duplex auto 是双工的协商模式为自动
双工模式有两种,一种是full(全双工),一种是half(半双工)
speed auto 是速率为协商模式为自动
一般的100M口支持: 10M,100M和自动模式
选择为自动模式则接口会和对端设备的接口进行协商,并自动选择最佳模式。
#ip access-group 10 out
将列表10所定义的条件应用禁止从此接口出去
该命令的详细说明如下:
ip access-group {[access-list-number] |[ name]} [in | out]
no ip access-group {[access-list-number] |[ name]} [in | out]
功能:将指定的访问列表应用到相关接口,并且指定acl起作用的方向。本命令的no操作为解除访问列表应用到相关接口,若没有指定方向,则默认为out;
若没有指定具体的[access-list-number] 或[name]而指定了方向,则默认为删除该方向上所有的访问列表的应用;若没有指定具体的[access-list-number] 或[name]也没有指定方向,则默认为删除out方向上所有的访问列表的应用。
参数:[access-list-number]为访问表表号,取值范围1~199;[name]为由ip access-list 命令指定的访问表名字,最长不超过8个字符;in为过滤入口的包;out为过滤出口的包。
缺省情况:没有任何访问表被应用至任何接口。若指定了绑定,而未指定方向,缺省为out。
命令模式:接口配置模式
使用指南:在访问列表应用到具体接口的具体方向之前,访问列表的规则是不起作用的。每个接口定义两个方向,即in和out方向。前者代表流入接口的方向,
后者代表流出接口的方向。规则可单独对in或out方向起作用,即只过滤入口的包或只过滤出口方向上的包,也可以两个方向都过滤。
应用到接口上的访问列表可以有多条,但只能有一条标准访问列表,对扩展访问列表来说,一个接口一个方向相同协议的访问列表只能有一条。访问列表的协议是指
每个表的协议缺省为这个表的第一条规则中指定要过滤的协议。若通过的信息包符合多条规则,则只有匹配的第一条规则有作用,匹配的顺序与规则应用到接口的先
后顺序一致。若规则中含有相互冲突的设置,以第一条匹配到的规则为准。
在当前时间不在分段时间过滤访问表设定的时间段时,将分段时间过滤访问表应用到接口是不起作用的,但等时间进入设定的时间段后,曾经应用到接口的分段时间过滤访问表会自动生效。
router ospf 10
Router ospf 10 中的 10 是这台路由器 Ospf 进程的 ID 号!
路由器和我们的PC一样,是多任务系统,理论上能够支持多个 OSPF 进程同时运行!此ID号仅本地有效! SNMP 是网络管理协议,OSPF
是路由协议,两者就不是一个东西,不能相提并论!
log-adjacency-changes
log-adjacency-changes命令 可用来激活路由协议邻接关系变化日志的功能(例如ospf或者ISIS等)。使用该命令来生成SYSLOG信息以用于网络操作与管理。日志信息对于故障排除也非常有用。log-adjacency-changes 是一个日志开关,意思是当 OSPF 探测到邻居关系发生变化时,将变化情况记录在系统日志里面 !
network 192.168.233.160 0.0.0.3 area 1
1 2 3 4 5 6 7 8 9 10 11 network 192.168.233.164 0.0.0.3 area 1 network 192.168.233.168 0.0.0.3 area 1 network 192.168.233.172 0.0.0.3 area 1 network 192.168.233.176 0.0.0.3 area 1 network 192.168.233.184 0.0.0.3 area 1 network 192.168.233.188 0.0.0.3 area 1 network 192.168.233.192 0.0.0.3 area 1 network 192.168.233.196 0.0.0.3 area 1 network 192.168.233.200 0.0.0.3 area 1 network 192.168.233.204 0.0.0.3 area 1 network 10.228.1.0 0.0.0.15 area 1
是使用 OSPF 向邻居发布路由信息! area 1 是 OSPF路由域中的 区域1,ospf 路由域分为骨干区域和非骨干区域,只有 area 0 是骨干区域,其他都是非骨干区域!
0.0.0.3表示: 反掩码,表示匹配反掩码为1的位
0.0.0.255实际上是0.0.0.1111 1111 只要192.168.2.xxxx xxxx的网段就应用该路由 我自己把反掩码中的0理解为固定位,1理解为自由位。固定位就是不能变的,自由位是能变的,其实就是对前面ip的修饰,固定位就是他的网络段
原文链接:https://blog.csdn.net/qq_31828929/article/details/71191679
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 PC与路由器的接口配置: interface FastEthernet0/0 ip address 192.168 .1 .254 255.255 .255 .0 duplex auto speed auto [(30 条消息) 思科实验之配置ACL_晚风挽着浮云的博客-CSDN博客_思科配置acl](https: interface FastEthernet0/0 ip address 192.168 .1 .254 255.255 .255 .0 no shutdown exit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 R1: interface GigabitEthernet0/0 ip address 172.16 .10 .1 255.255 .255 .0 no shutdown #开启接口 exit router ospf 10 #开启ospf 进程号为10 network 172.16 .10 .0 0.0 .0 .255 area 1 #宣告直连的网段;网段的反掩码;其直连的网段属于area1区域 R2: interface GigabitEthernet0/0 ip address 172.16 .10 .2 255.255 .255 .0 no shu interface GigabitEthernet0/1 ip address 172.16 .20 .1 255.255 .255 .0 no shu exit router ospf 10 network 172.16 .10 .0 0.0 .0 .255 area 1 #宣告直连,其直连的网段属于area1 区域 network 172.16 .20 .0 0.0 .0 .255 area 0 #area0是骨干区域 R3: interface GigabitEthernet0/0 ip address 172.16 .20 .2 255.255 .255 .0 no shu interface GigabitEthernet0/1 ip address 172.16 .30 .1 255.255 .255 .0 no shu exit router ospf 10 network 172.16 .20 .0 0.0 .0 .255 area 0 network 172.16 .30 .0 0.0 .0 .255 area 2 R4: interface GigabitEthernet0/0 ip address 172.16 .30 .2 255.255 .255 .0 no shu exit router ospf 10 network 172.16 .30 .0 0.0 .0 .255 area 2 show ip route ping 172.16 .30 .2 https:
Loopback 是路由器里面的一个逻辑接口。逻辑接口是指能够实现数据交换功能,但是物理上不存在、需要通过配置建立的接口。Loopback接口一旦被创建,其物理状态和链路协议状态永远是Up,即使该接口上没有配置IP地址
Loopback接口创建后一直保持UP状态,用户可通过配置Loopback接口达到提高网络可靠性的目的。
(30条消息) Loopback接口的主要作用及Loopback端口配置_JackLiu16的博客-CSDN博客_交换机loopback接口
OSPF多域配置_wx627255bd4ac6d的技术博客_51CTO博客
实训3 路由交换综合
1 2 3 4 5 6 7 实训要求 1.试验台环境:路由器为2811,交换机3560、2950; 2.规划IP,配置接口,启动静态或动态路由协议,保障网络连通性; 3.划分两个VLAN,VLAN 10采用192.168.10.0/24,VLAN 20采用192.168.20.20; 4.能够实现VLAN间路由; 5.禁止VLAN 20中的主机访问WWW服务,但不禁止Ping (VLAN10中主机可以访问WWW)。 6.VLAN 20需要配置DHCP。
(30条消息) 交换机与路由器的通信的配置(2020.7.15)_penguinhd的博客-CSDN博客
SW13
Enable
Conf t
Vlan 10
Exit
Interface f0/1
Switchport access vlan 10
Exit
Interface f0/2
Switchport mode trunk
sw14
Enable
Conf t
Vlan 20
Exit
Interface f0/2
Switchport access vlan 20
Exit
Interface f0/1
Switchport mode trunk
sw12
enable
conf t
vlan 10
exit
vlan 20
interface range f0/1-3
switchport mode trunk
sw1
enable
conf t
vlan 10
exit
vlan 20
exit
interface f0/1
switchport tr en do
switchport mode trunk
exit
interface vlan 10
ip address 192.168.10.1 255.255.255.0
exit
interface vlan 20
ip address 192.168.20.1 255.255.255.0
exit
ip routing
Switch(config)#interface f0/2
Switch(config-if)#no switchport(使其成为路由器接口)
Switch(config-if)#ip address 192.168.30.1 255.255.255.0
route 4
enable
config t
interface f0/0
no shutdown
ip address 192.168.30.2 255.255.255.0
exit
interface f0/1
no shutdown
ip address 192.168.40.1 255.255.255.0
route 5
enable
conf t
interface f0/0
no shutdown
ip address 192.168.40.2 255.255.255.0
exit
interface f0/1
no shutdown
ip address 192.168.50.1 255.255.255.0
什么是ACL?
ACL全称访问控制列表(Access Control List),主要通过配置一组规则进行过滤路由器或交换机接口进出的数据包,
是控制访问的一种网络技术手段 , ACL适用于所有的被路由支持的协议,如IP、tcp、udp、ftp、www等。
什么是反掩码?
反掩码就是通配符掩码 , 通过标记0和1告诉设备应该匹配到哪位。 在反掩码中,相应位为1的地址在比较中忽略,
为0的必须被检查。IP地址与反掩码都是32位的数 由于跟子网掩码刚好相反,所以也叫反掩码 。
路由器使用的通配符掩码与源或目标地址一起来分辨匹配的地址范围,它与子网掩码不同。它不像子网掩码告诉
路由器IP地址是属于哪个子网(网段),通配符掩码告诉路由器为了判断出匹配,它需要检查IP地址中的多少位。
例如:
255.255.255.0 反掩码(wildcard-mask)就是0.0.0.255
255.255.255.248 反掩码(wildcard-mask)就是0.0.0.7
ACL工作原理:
ACL使用包过滤技术,在路由器上读取OSI七层模型的第3层和第4层包头中的信息。如源地址,目标地址,源端口,目标端口等,根据预先定义好的规则,对包进行过滤,从而达到访问控制的目的。
对于路由器接口而言,ACL是有两个方向:
**注意:**如果发现没有匹配的ACL规则,默认会丢弃该数据包,思科ACL规则默认会有一条隐藏的deny any any规则,而华三ACL规则默认是permit any any规则。
**入站----**如果是入站访问列表,则当路由器接收到数据包时,Cisco IOS 软件将检查访问列表中的条件语句,看是否有匹配。如果数据包被允许,则软件将继续处理该数据包。如果数据包被拒绝,则软件会丢弃该数据包。
**出站----**如果是出站访问列表,则当软件到接收数据包并将群其路由至出站接口后,软件将检查访问列表中的条件语句,看是否有匹配。如果数据包被允许,则软件会发送该数据包。如果数据包被拒绝,则软件会丢弃该数据包。
ACL两种类型:
**标注:**允许在标准ACL和扩展ACL中使用名称代替访问控制列表号。
1、 标准的ACL
根据数据包的源IP地址来控制允许转发或拒绝数据包,访问控制列表号1~99。
标准访问控制列表配置命令如下:
Router(config)#access-list access-list-number {permit|deny} source [souce-wildcard]
或者
Router(config)#ip access-list standard access-list-number
Router(config-std-nacl)#Sequence Number{permit|deny} source [souce-wildcard]
下面是命令参数的详细说明
access-list-number:访问控制列表号,标准ACL取值是1-99,可以使用名称替代列表号。
Sequence Number:每条ACL规则列表序列号,可使用范围1-2147483647。
permit | deny:如果满足规则,则允许/拒绝通过。
source:数据包的源地址,可以是主机地址,也可以是网络地址
2、 扩展的ACL
根据数据包的源IP地址、目的IP地址、指定协议,端口、标志和时间来控制允许转发或拒绝数据包,访问控制列表号100~199
扩展访问控制列表配置命令如下:
Router(config)#access-list access-list-number {permit|deny} protocol {source souce-wildcard destination destination-wildcard} [operator operan]
或者
Router(config)#ip access-list extended access-list-number
Router(config-std-nacl)#{permit|deny} protocol {source souce-wildcard destination destination-wildcard} [operator operan]
下面是命令参数的详细说明
access-list-number:访问控制列表号,扩展ACL取值100-199,可以使用名称替代列表号。
Sequence Number:每条ACL规则列表序列号,可使用范围1-2147483647。
permit|deny:如果满足规则,则允许/拒绝通过。
protocol:用来指定协议的类型,如IP,TCP,UDP,ICMP等。
source、destination:源和目的,分别用来标示源地址和目的地址。
souce-wildcard、destination-wildcard:子网反码,souce-wildcard是源反码,destination-wildcard是目标反码。
operator operan:lt(小于)、gt(大于)、eq(等于)、neq(不等于)、rand(范围端口号)等。
DHCP
DHCP全称为Dynamic Host Configuration Protocol,中文含义为“动态主机配置协议”,通常被应用在大型的局域网络环境中,主要作用是集中管理、分配IP地址,使网络环境中的主机动态获得IP地址、Gateway地址、DNS 服务器地址等信息,并能够提升地址的使用率。
DHCP协议采用客户端/服务器模型,主机地址的动态分配任务由网络主机驱动。当DHCP服务器接收到来自网络主机申请地址的信息时,才会向网络主机发送相关的地址配置等信息,以实现网络主机地址信息的动态配置。
DHCP服务器 就是自动给电脑分配IP地址和子网掩码的服务器。比如我们设置了路由器的DHCP服务器,让DHCP服务器自动分配IP地址,从192.168.1.1 00到192.168.1.199(子网掩码会自动设置,我们无需设置)。
实训4 RIP一般配置方法
RIP(Routing Information protocol) 路由信息协议.
是一种内部网关协议(IGP),是一种动态路由选择协议,用于自治系统(AS)内的路由信息的传递。RIP协议基于距离矢量算法(DistanceVectorAlgorithms),使用“跳数”(即metric)来衡量到达目标地址的路由距离。RIP通过UDP报文进行路由信息交换,使用的端口号为520.
这种协议的路由器只关心自己周围的世界,只与自己相邻的路由器交换信息,范围限制在15跳(15度)之内 ,再远,它就不关心了。RIP应用于OSI网络七层模型的应用层。各厂家定义的管理距离(AD,即优先级)如下:华为定义的优先级是100,思科定义的优先级是120。
第一步:将每个设备的IP地址配好
Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#interface g0/0
Router(config-if)#ip address 192.168.1.1 255.255.255.0
Router(config-if)#no shutdown
Router(config-if)#exit
Router(config)#interface Se0/3/0
Router(config-if)#ip address 10.0.0.1 255.0.0.0
Router(config-if)#no shutdown
Router(config-if)#end
Router#
%SYS-5-CONFIG_I: Configured from console by console
Router#
第二步:配置rip路由
Router(config)#hostname R0
R0(config)#end
R0#
%SYS-5-CONFIG_I: Configured from console by console
R0#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
R0(config)#route rip
R0(config-router)#network 192.168.1.0
R0(config-router)#network 10.0.0.0
R0(config-router)#end
实训5 华为交换初步
1 2 3 4 实训目的: 了解VLAN的划分方法; 了解VLAN特性; 了解Trunk的配置方法
(30条消息) 二层交换机实现vlan 功能 (Cisco Packer Tracer 模拟器)_sizaif的博客-CSDN博客
主机配置:
Switch>en
Switch#conf
Switch(config)#vlan 10 // 创建 vlan 10
Switch(config-vlan)#vlan 20 // 创建 vlan 20
Switch(config-vlan)#EXIT
Switch(config-if)#interface fa0/1 // 进入端口 f0/1 并配置为接入到vlan10 的access 模式
Switch(config-if)#switchport mode access
Switch(config-if)#switchport access vlan 10
Switch(config-if)#interface fa0/2 //进入端口 f0/2 并配置为接入到vlan20 的access 模式
Switch(config-if)#switchport mode access
Switch(config-if)#switchport access vlan 20
交换机配置:
Switch>en
Switch#conf
Switch(config)#interface fa0/24 // 进入端口f0/24 并设置为trun 模式,允许所以vlan通过
Switch(config-if)#switchport mode access
Switch(config-if)#switchport mode trunk
Switch(config-if)#switchport trunk allowed vlan all
192.168.1.1 ----- >ping 192.168.2.2 ping不通 :同一交换机下,不同vlan,不同网段
192.168.1.1 ----- > ping 192.168.1.4 ping通: 跨交换机,同一vlan,同一网段
总结
1 2 3 4 5 6 Switch#show ip route Switch#show vlan Switch#write #保存已写的内容 PC>ipconfig IP PC>ping 192.168 .2 .2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 二层交换机 Switch>en Switch#conf t #设置vlan Switch (config) #vlan 2 Switch (config) #vlan 3 Switch (config-vlan) #exit #同一个vlan交流,配置vlan就用switchport access vlan n就足够了 Switch (config) #int fa 0/2 Switch (config-if ) #switchport access vlan 2 Switch (config-if ) #int fa 0/3 Switch (config-if ) #switchport access vlan 3 #想vlan2和vlan3交流就得使用trunk协议,二层交换机上配置如下: Switch (config-if ) #int fa 0/1 Switch (config-if ) #switchport mode trunk Switch (config-if ) #end
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 三层交换机 Switch>en Switch#conf t Switch(config)#vlan 2 Switch(config)#vlan 3 Switch(config-vlan)#exit #三层交换机口配置 Switch(config)#int fa 0/1 Switch(config-if )#switchport trunk encapsulation dot1q Switch(config-if )#switchport mode trunk Switch(config-if )#switchport trunk allowed vlan 2,3 Switch(config-if )#exit #启动vlan n的使用 Switch(config)#int vlan 2 Switch(config-if )#ip address 192.168.1.1 255.255.255.0 Switch(config-if )#no shutdown Switch(config-if )#exit (vlan 3 同理) #开启三层交换机默认路由 Switch(config)#ip routing Switch(config)#exit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ##配置VTP服务器https: #三层交换机实现服务器 Switch>enable Switch#vlan database Switch(vlan)#vtp domain CCTV Switch(vlan)#vtp server ##创建VLAN Switch (vlan) #vlan 10 name VLAN10 Switch (vlan) #vlan 20 name VLAN20 Switch (vlan) #exit ##配置VLAN IP地址 Switch#configure terminal Switch (config) #interface vlan 10 Switch (config-if ) #ip address 192.168.10.1 255.255.255.0 Switch (config-if ) #exit Switch (config) #interface vlan 20 Switch (config-if ) #ip address 192.168.20.1 255.255.255.0 Switch (config-if ) #exit ##开启三层交换机默认路由 3560SW (config) #ip routing #设置端口汇聚(trunk) Switch (config) #interface range fastEthernet 0/22-24 Switch (config-if -range) #switchport trunk encapsulation dot1q Switch (config-if -range) #switchport mode trunk Switch (config-if -range) #no shutdown Switch (config-if -range) #exit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #二层交换机作为VTP客户端 Switch#vlan database Switch(vlan)#vtp domain CCTV Switch(vlan)#vtp client Switch(vlan)#exit ##设置端口汇聚(trunk) Switch#configure terminal Switch(config)#interface fastEthernet 0/24 Switch(config-if )#switchport mode trunk Switch(config-if )#no shutdown Switch(config-if )#exit ##分配VLAN所属端口 Switch#configure terminal Switch(config)#interface range fastEthernet 0/1-5 Switch(config-if -range)#switchport access vlan 10 Switch(config-if -range)#switchport mode access Switch(config-if -range)#no shutdown Switch(config-if -range)#exit
1 2 3 4 5 #PC机与路由器间的配置: Router(config-if )#interface FastEthernet0/0 Router(config-if )#ip address 192.168.1.254 255.255.255.0 Router(config-if )#no shutdown Router(config-if )#exit
1 2 3 4 5 6 7 8 #路由器与路由器间的配置 Router(config-if )#interface GigabitEthernet0/0 Router(config-if )#ip address 172.16.10.1 255.255.255.0 Router(config-if )#no shutdown Router(config-if )#exit #ospf配置 Router(config)#router ospf 10 Router(config-router)#network 172.16.10.0 0.0.0.255 area 1
1 2 3 4 5 6 7 #配置loopback接口(ip自定义) Router(config)#interface loopback 0 Router(config-if )#ip address 1.1.1.1 255.255.255.255 Router(config-if )#no shutdown Router(config)#interface loopback 1 Router(config-if )#ip address 192.168.1.1 255.255.255.0 Router(config-if )#no shutdown
1 2 3 4 5 #路由器地址配置 Router(config)#interface g0/0 Router(config-if )#ip address 192.168.1.1 255.255.255.0 Router(config-if )#no shutdown Router(config-if )#exit
1 2 3 4 5 6 #路由器RIP配置 Router(config)#hostname R0 R0(config)#route rip R0(config-router)#network 192.168.1.0 R0(config-router)#network 10.0.0.0 R0(config-router)#end
1 2 3 4 5 6 7 主机的vlan配置: Switch(config)#vlan 10 Switch(config-vlan)#EXIT Switch (config-if ) #interface fa0/1 Switch (config-if ) #switchport mode access Switch (config-if ) #switchport access vlan 10
1 2 3 4 5 二层交换机间的配置: Switch(config)#interface fa0/24 Switch(config-if )#switchport mode access Switch(config-if )#switchport mode trunk Switch(config-if )#switchport trunk allowed vlan all
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 路由器与交换机间的配置: (1 )交换机端口配置 #f0/1 协议配置 Switch(config)#interface f0/1 Switch(config-if )#switchport trunk encapsulation dot1q Switch(config-if )#switchport mode trunk Switch(config-if )#exit #f0/1 IP配置 Switch(config)#interface f0/1 Switch(config-if )#no switchport(使其成为路由器接口) Switch(config-if )#ip address 192.168.30.1 255.255.255.0 (2 )路由器配置 Switch(config)#interface f0/0 Switch(config-if )#no shutdown Switch(config-if )#ip address 192.168.30.2 255.255.255.0 Switch(config-if )#exit
1 2 3 4 5 6 7 8 9 10 11 #DHCP:动态地址获取 Switch(config)#ip dhcp pool vlan20 Switch(dhcp-config)#network 192.168.20.254 255.255.255.0 Switch(dhcp-config)#default-router 192.168.20.254 Switch(dhcp-config)#dns-server 8.8.8.8 Switch(dhcp-config)#end #telnet:远程登陆 Switch(config)#enable password 123 Switch(config)# line vty 0 2 Switch(config-line)# password cisco