网络编程练习这些就ok
1,什么是C/S架构?
1 2 3 4 5 6 7 8 9 | C指的是client(客户端软件),S指的是Server(服务端软件) 一个C / S架构就是,实现服务端软件与客户端软件基于网络通信。 互联网中处处是C / S架构 如 12306 网站是服务端,你的浏览器是客户端(B / S架构也是C / S架构的一种) 腾讯作为服务端为你提供视频,你得下个腾讯视频客户端才能看它的视频) C / S架构与socket的关系: 我们学习socket就是为了完成C / S架构的开发 |
2,互联网协议是什么?分别介绍五层协议中每一层的功能?
1 2 3 4 5 6 7 | 英语成为世界上所有人通信的统一标准,计算机之间的通信也应该有一个像英语一样的通信标准, 这个标准称之为互联网协议, 可以很明确地说:互联网协议就是计算机界的英语,网络就是物理链接 介质 + 互联网协议。 我们需要做的是,让全世界的计算机都学会互联网协议,这样任意一台计算机在 发消息时都严格按照协议规定的格式去组织数据,接收方就可以按照相同的协议解析出结果了,这就 实现了全世界的计算机都能无障碍通信。 按照功能不同,人们将互联网协议分为osi七层或tcp / ip五 层或tcp / ip四层(我们只需要掌握tcp / ip五层协议即可),这种分层就好比是学习英语的几个阶段, 每个阶段应该掌握专门的技能或者说完成特定的任务,比如: 1 、学音标 2 、学单词 3 、学语法 4 、写作文 |
1 2 3 4 5 | 简单说,计算机之间的通信标准,就称为互联网协议<br> 按照功能不同,人们将互联网协议分为osi七层或tcp / ip五层或tcp / ip四层<br> tcp / ip四层:应用层,传输层,网络层,网络接口层<br> tcp / ip五层:应用层,传输层,网络层,数据链路层,物理层<br> osi七层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层 |
3,基于tcp协议通信,为何建立链接需要三次握手,而断开链接却需要四次挥手
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 为什么要三次挥手? 在只有两次“握手”的情形下,假设Client想跟Server建立连接,但是却因为中途连接请求的 数据报丢失了,故Client端不得不重新发送一遍;这个时候Server端仅收到一个连接请求,因此 可以正常的建立连接。但是,有时候Client端重新发送请求不是因为数据报丢失了,而是有可能 数据传输过程因为网络并发量很大在某结点被阻塞了,这种情形下Server端将先后收到 2 次请求, 并持续等待两个Client请求向他发送数据...问题就在这里,Cient端实际上只有一次请求,而 Server端却有 2 个响应,极端的情况可能由于Client端多次重新发送请求数据而导致Server端 最后建立了N多个响应在等待,因而造成极大的资源浪费!所以,“三次握手”很有必要! 为什么要四次挥手? 试想一下,假如现在你是客户端你想断开跟Server的所有连接该怎么做? 第一步,你自己先停止向Server端发送数据,并等待Server的回复。但事情还没有完, 虽然你自身不往Server发送数据了,但是因为你们之前已经建立好平等的连接了, 所以此时他也有主动权向你发送数据;故Server端还得终止主动向你发送数据, 并等待你的确认。其实,说白了就是保证双方的一个合约的完整执行! |
三次握手:client发送请求建立通道;server收到请求并同意,同时也发送请求建通道;client收到请求并同意,建立完成
四次挥手:client发送请求断开通道;server收到请求并同意,同时还回复client上一条消息;server也发送请求断开通道;client受到消息结束
1 2 3 4 5 6 7 8 9 10 11 12 | 为什么TCP协议终止链接要四次? 1 、当主机A确认发送完数据且知道B已经接受完了,想要关闭发送数据口(当然确认信号还是可以发), 就会发FIN给主机B。 2 、主机B收到A发送的FIN,表示收到了,就会发送ACK回复。 3 、但这是B可能还在发送数据,没有想要关闭数据口的意思,所以FIN与ACK不是同时发送的, 而是等到B数据发送完了,才会发送FIN给主机A。 4 、A收到B发来的FIN,知道B的数据也发送完了,回复ACK, A等待 2MSL 以后,没有收到B传来的 任何消息,知道B已经收到自己的ACK了,A就关闭链接,B也关闭链接了。 |
4,为何基于tcp协议的通信比基于udp协议的通信更可靠?
tcp:可靠 对方给了确认收到信息,才发下一个,如果没收到确认信息就重发
udp:不可靠 一直发数据,不需要对方回应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ( 1 )UDP:user datagram protocol(用户数据报协议) 特点: —— 1 :面向无连接:传输数据之前源端和目的端不需要建立连接 —— 2 :每个数据报的大小都限制在 64k ( 8 个字节)以内 —— 3 :面向报文的不可靠协议(即发出去的数据不一定会接收到) —— 4 :传输速率快,效率高 —— 5 :现实生活实例:邮局寄件,实时在线聊天,视频协议等等 ( 2 )TCP:transmission control protocol(传输控制协议) 特点: —— 1 :面向连接:传输数据之前需要建立连接 —— 2 :在连接过程中进行大量的数据传输 —— 3 :通过“三次握手”的方式完成连接,是安全可靠的协议 —— 4 :传输效率低,速度慢 |
5,流式协议指的是什么协议,数据报协议指的是什么协议?
1 2 3 4 5 | TCP协议,可靠传输 数据报协议: UDP协议,不可传输 也就是TCP和UDP的区别: TCP是面向连接的,可靠的字节流服务 UDP是面向无连接的数据报服务 |
6,什么是socket?简述基于tcp协议的套接字通信流程流式协议:
1 2 3 4 5 6 7 8 | Socket是应用层与TCP / IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中, Socket其实就是一个门面模式,它把复杂的TCP / IP协议族隐藏在Socket接口后面, 对用户来说,一组简单的接口就是全部。 服务端:创建socket对象,绑定ip端口bind(), 设置最大链接数listen(), accept()与客户端 的connect()创建双向管道, send(), recv(),close() 客户端:创建socket对象,connect()与服务端accept()创建双向管道 , send(), recv(),close() |
7,什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?
1 2 3 | 粘包:数据粘在一起,主要因为:接收方不知道消息之间的界限,不知道一次性提取 多少字节的数据造成的数据量比较小,时间间隔比较短,就合并成了一个包, 这是底层的一个优化算法(Nagle算法) |
8,基于socket开发一个聊天程序,实现两端互相发送和接收消息
服务端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # _*_ coding: utf-8 _*_ # 8,基于socket开发一个聊天程序,实现两端互相发送和接收消息 import socket ip_port = ( '127.0.0.1' , 8088 ) link = socket.socket(socket.AF_INET,socket.SOCK_STREAM) link.bind(ip_port) link.listen( 5 ) print ( "等待数据连接:。。》》" ) # 阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象 conn, addr = link.accept() client_data = conn.recv( 1024 ) print ( "这是收到的消息:" ,client_data.decode( 'utf-8' )) conn.send(client_data.upper()) conn.close() link.close() |
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # _*_ coding: utf-8 _*_ # 8,基于socket开发一个聊天程序,实现两端互相发送和接收消息/ import socket ip_port = ( '127.0.0.1' , 8088 ) link = socket.socket(socket.AF_INET,socket.SOCK_STREAM) link.connect(ip_port) print ( "开始发送数据" ) cmd = input ( "请输入:>>" ).strip() link.send(cmd.encode( 'utf-8' )) data = link.recv( 1028 ) print (data) link.close() |
9,基于tcp socket,开发简单的远程命令执行程序,允许用户执行命令,并返回结果
服务端:
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 | # _*_ coding: utf-8 _*_ # 9,基于tcp socket,开发简单的远程命令执行程序,允许用户执行命令,并返回结果 import socket import struct import subprocess ip_port = ( '127.0.0.1' , 9999 ) sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sk.bind(ip_port) sk.listen( 5 ) while True : #连接循环 conn,addr = sk.accept() print (conn,addr) while True : #通信循环 client_data = conn.recv( 1024 ) #处理过程 res = subprocess.Popen(client_data.decode( 'utf-8' ),shell = True , stdout = subprocess.PIPE, stderr = subprocess.PIPE) stdout = res.stdout.read() stderr = res.stderr.read() # 先发报头(转成固定长度的bytes类型,那么怎么转呢?就用到了struct模块) length = len (stdout) + len (stderr) header = struct.pack( 'i' ,length) conn.send(header) conn.send(stderr) conn.send(stdout) conn.close() sk.close() conn.close() sk.close() |
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # _*_ coding: utf-8 _*_ # 9,基于tcp socket,开发简单的远程命令执行程序,允许用户执行命令,并返回结果 import socket import struct ip_port = ( '127.0.0.1' , 9999 ) sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sk.connect(ip_port) while True : cmd = input ( "请输入命令:>>" ).strip() if not cmd: continue sk.send(cmd.encode( 'utf-8' )) header_struct = sk.recv( 1024 ) unpack_res = struct.unpack( 'i' ,header_struct) total_size = unpack_res[ 0 ] recv_size = 0 total_data = b'' while recv_size < total_size: recv_data = sk.recv( 1024 ) recv_size + = len (recv_data) total_data + = recv_data print ( "返回的消息:%s" % total_data.decode( 'gbk' )) sk.close() |
10,基于tcp协议编写简单FTP程序,实现上传、下载文件功能,并解决粘包问题
客户端
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 | # _*_ coding: utf-8 _*_ import socket import struct import json downlaod_dir = r 'D:\文件传输\client\download' ip_port = ( '127.0.0.1' , 8808 ) phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(ip_port) while True : cmd = input ( ">>>" ).strip() #get D:\文件传输\server\a.avi if not cmd: continue phone.send(cmd.encode( 'utf-8' )) #接受文件的内容,以写的方式打开一个新文件,接受服务端发来的文件内容,并写入客户端的新文件 #第一步,先收报头的长度,然后解包 obj = phone.recv( 1024 ) header_size = struct.unpack( 'i' ,obj)[ 0 ] #第二部 再收报头 header_bytes = phone.recv(header_size) #第三部,从报头中解析除对真实数据的描述信息 header_json = header_bytes.decode( 'utf-8' ) header_dic = json.loads(header_json) ''' header_dic = { 'filename':filename, #a.avi 'md5':'dsdsd', 'file_size':os.path.getsize(filename) }''' print (header_dic) total_size = header_dic[ 'file_size' ] filename = header_dic[ 'filename' ] #第四步,接受真实的数据 with open ( '%s/%s' % (downlaod_dir,filename), 'wb' ) as f: recv_size = 0 # recv_data = b'' while recv_size <total_size: res = phone.recv( 1024 ) # recv_data += res f.write(res) recv_size + = len (res) print ( "总大小: %s \n已经下载大小 :%s" % (total_size,recv_size)) # print(recv_data.decode('utf-8')) phone.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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # _*_ coding: utf-8 _*_ import subprocess import socket import struct import json import os share_dir = r '/文件传输/server/share' phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) ip_port = ( '127.0.0.1' , 8808 ) phone.bind(ip_port) phone.listen( 5 ) print ( "starting...." ) while True : #链接循环 conn,client_addr = phone.accept() print (client_addr) while True : #通信循环 try : #收命令 res = conn.recv( 1024 ) #b'get a.txt' if not res : continue #解析命令,提取相应的参数 cmds = res.decode( 'utf-8' ).split() filename = cmds[ 1 ] #以读的方式打开文件,读取文件内容发送给客户端 # with open(filename,'rb') as f: # conn.s #制定固定长度的报头 header_dic = { 'filename' :filename, #a.avi 'md5' : 'dsdsd' , 'file_size' :os.path.getsize(r "%s/%s" % (share_dir,filename)) } header_json = json.dumps(header_dic) header_bytes = header_json.encode( 'utf-8' ) #先发送报头的长度 conn.send(struct.pack( 'i' , len (header_bytes))) #再发报头 conn.send(header_bytes) #再发真实的数据 with open ( '%s/%s' % (share_dir,filename), 'rb' ) as f: # conn.send(f.read()) for line in f: conn.send(line) except ConnectionResetError: break conn.close() phone.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 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 | # _*_ coding: utf-8 _*_ import socket import os import struct import pickle dirname = os.path.dirname(os.path.abspath(__file__)) filepath = os.path.join(dirname, 'share' ) def get(cmds,conn): filename = cmds[ 1 ] file_path = os.path.join(filepath, filename) if os.path.isfile(file_path): header = { 'filename' : filename, 'md5' : 'xxxxxx' , 'file_size' : os.path.getsize(file_path) } header_bytes = pickle.dumps(header) conn.send(struct.pack( 'i' , len (header_bytes))) conn.send(header_bytes) with open (file_path, 'rb' ) as f: for line in f: conn.send(line) else : conn.send(struct.pack( 'i' , 0 )) def put(cmds,conn): pass def run(): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(( '127.0.0.1' , 8080 )) server.listen( 5 ) print ( 'starting...' ) while True : conn, client_addr = server.accept() print (client_addr) while True : try : res = conn.recv( 1024 ) if not res: continue cmds = res.decode( 'utf-8' ).split() if cmds[ 0 ] = = 'get' : get(cmds,conn) elif cmds[ 0 ] = = 'put' : put(cmds,conn) except ConnectionResetError: break conn.close() server.close() if __name__ = = '__main__' : run() |
函数版本客户端
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 | # _*_ coding: utf-8 _*_ import socket import struct import pickle import os dirname = os.path.dirname(os.path.abspath(__file__)) filepath = os.path.join(dirname, 'download' ) def get(client): obj = client.recv( 4 ) header_size = struct.unpack( 'i' , obj)[ 0 ] if header_size = = 0 : print ( '文件不存在' ) else : header_types = client.recv(header_size) header_dic = pickle.loads(header_types) print (header_dic) file_size = header_dic[ 'file_size' ] filename = header_dic[ 'filename' ] with open ( '%s/%s' % (filepath, filename), 'wb' ) as f: recv_size = 0 while recv_size < file_size: res = client.recv( 1024 ) f.write(res) recv_size + = len (res) print ( '总大小:%s 已下载:%s' % (file_size, recv_size)) def put(): pass def run(): client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(( '127.0.0.1' , 8080 )) while True : msg = input ( ">>>:" ).strip() # get a.txt if not msg: continue client.send(msg.encode( 'utf-8' )) cmds = msg.split() if cmds[ 0 ] = = 'get' : get(client) elif cmds[ 0 ] = = 'put' : put() client.close() if __name__ = = '__main__' : run() |
面向对象版本服务端
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 | # _*_ coding: utf-8 _*_ import socket import os import struct import pickle class TCPServer: address_family = socket.AF_INET socket_type = socket.SOCK_STREAM listen_count = 5 max_recv_bytes = 8192 coding = 'utf-8' allow_reuse_address = False # 下载的文件存放路径 down_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'share' ) # 上传的文件存放路径 upload_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'upload' ) def __init__( self ,server_address,bind_and_listen = True ): self .server_address = server_address self .socket = socket.socket( self .address_family, self .socket_type) if bind_and_listen: try : self .server_bind() self .server_listen() except Exception: self .server_close() def server_bind( self ): if self .allow_reuse_address: self .socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1 ) self .socket.bind( self .server_address) def server_listen( self ): self .socket.listen( self .listen_count) def server_close( self ): self .socket.close() def server_accept( self ): return self .socket.accept() def conn_close( self ,conn): conn.close() def run( self ): print ( 'starting...' ) while True : self .conn, self .client_addr = self .server_accept() print ( self .client_addr) while True : try : res = self .conn.recv( self .max_recv_bytes) if not res: continue cmds = res.decode( self .coding).split() if hasattr ( self ,cmds[ 0 ]): func = getattr ( self ,cmds[ 0 ]) func(cmds) except Exception: break self .conn_close( self .conn) def get( self ,cmds): """ 下载 1.找到下载的文件 2.发送 header_size 3.发送 header_bytes file_size 4.读文件 rb 发送 send(line) 5.若文件不存在,发送0 client提示:文件不存在 :param cmds: 下载的文件 eg:['get','a.txt'] :return: """ filename = cmds[ 1 ] file_path = os.path.join( self .down_filepath, filename) if os.path.isfile(file_path): header = { 'filename' : filename, 'md5' : 'xxxxxx' , 'file_size' : os.path.getsize(file_path) } header_bytes = pickle.dumps(header) self .conn.send(struct.pack( 'i' , len (header_bytes))) self .conn.send(header_bytes) with open (file_path, 'rb' ) as f: for line in f: self .conn.send(line) else : self .conn.send(struct.pack( 'i' , 0 )) def put( self ,cmds): """ 上传 1.接收4个bytes 得到文件的 header_size 2.根据 header_size 得到 header_bytes header_dic 3.根据 header_dic 得到 file_size 3.以写的形式 打开文件 f.write() :param cmds: 下载的文件 eg:['put','a.txt'] :return: """ obj = self .conn.recv( 4 ) header_size = struct.unpack( 'i' , obj)[ 0 ] header_bytes = self .conn.recv(header_size) header_dic = pickle.loads(header_bytes) print (header_dic) file_size = header_dic[ 'file_size' ] filename = header_dic[ 'filename' ] with open ( '%s/%s' % ( self .upload_filepath, filename), 'wb' ) as f: recv_size = 0 while recv_size < file_size: res = self .conn.recv( self .max_recv_bytes) f.write(res) recv_size + = len (res) tcp_server = TCPServer(( '127.0.0.1' , 8080 )) tcp_server.run() tcp_server.server_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 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 | # _*_ coding: utf-8 _*_ import socket import struct import pickle import os class FTPClient: address_family = socket.AF_INET socket_type = socket.SOCK_STREAM # 下载的文件存放路径 down_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'download' ) # 上传的文件存放路径 upload_filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'share' ) coding = 'utf-8' max_recv_bytes = 8192 def __init__( self , server_address, connect = True ): self .server_address = server_address self .socket = socket.socket( self .address_family, self .socket_type) if connect: try : self .client_connect() except Exception: self .client_close() def client_connect( self ): self .socket.connect( self .server_address) def client_close( self ): self .socket.close() def run( self ): while True : # get a.txt 下载 put a.txt 上传 msg = input ( ">>>:" ).strip() if not msg: continue self .socket.send(msg.encode( self .coding)) cmds = msg.split() if hasattr ( self ,cmds[ 0 ]): func = getattr ( self ,cmds[ 0 ]) func(cmds) def get( self , cmds): """ 下载 1.得到 header_size 2.得到 header_types header_dic 3.得到 file_size file_name 4.以写的形式 打开文件 :param cmds: 下载的内容 eg: cmds = ['get','a.txt'] :return: """ obj = self .socket.recv( 4 ) header_size = struct.unpack( 'i' , obj)[ 0 ] if header_size = = 0 : print ( '文件不存在' ) else : header_types = self .socket.recv(header_size) header_dic = pickle.loads(header_types) print (header_dic) file_size = header_dic[ 'file_size' ] filename = header_dic[ 'filename' ] with open ( '%s/%s' % ( self .down_filepath, filename), 'wb' ) as f: recv_size = 0 while recv_size < file_size: res = self .socket.recv( self .max_recv_bytes) f.write(res) recv_size + = len (res) print ( '总大小:%s 已下载:%s' % (file_size, recv_size)) else : print ( '下载成功!' ) def put( self , cmds): """ 上传 1.查看上传的文件是否存在 2.上传文件 header_size 3.上传文件 header_bytes 4.以读的形式 打开文件 send(line) :param cmds: 上传的内容 eg: cmds = ['put','a.txt'] :return: """ filename = cmds[ 1 ] file_path = os.path.join( self .upload_filepath, filename) if os.path.isfile(file_path): file_size = os.path.getsize(file_path) header = { 'filename' : os.path.basename(filename), 'md5' : 'xxxxxx' , 'file_size' : file_size } header_bytes = pickle.dumps(header) self .socket.send(struct.pack( 'i' , len (header_bytes))) self .socket.send(header_bytes) with open (file_path, 'rb' ) as f: send_bytes = b'' for line in f: self .socket.send(line) send_bytes + = line print ( '总大小:%s 已上传:%s' % (file_size, len (send_bytes))) else : print ( '上传成功!' ) else : print ( '文件不存在' ) ftp_client = FTPClient(( '127.0.0.1' , 8080 )) ftp_client.run() ftp_client.client_close() 客户端 |
11,基于udp协议编写程序,实现功能
服务端:
1 2 3 4 5 6 7 8 9 10 | # _*_ coding: utf-8 _*_ import socket ip_port = ( '127.0.0.1' , 8808 ) udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) udp_server_client.bind(ip_port) while True : conn,addr = udp_server_client.recvfrom( 1024 ) print (conn,addr) udp_server_client.sendto(conn.upper(),addr) |
客户端:
1 2 3 4 5 6 7 8 9 10 11 | # _*_ coding: utf-8 _*_ import socket ip_port = ( '127.0.0.1' , 8808 ) udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True : cmd = input ( ">>>>" ).strip() if not cmd: continue udp_server_client.sendto(cmd.encode( 'utf-8' ),ip_port) back_cmd,addr = udp_server_client.recvfrom( 1024 ) print (back_cmd.decode( 'utf-8' )) |
UDP不会发生粘包现象,下面举例说明
客户端
1 2 3 4 5 6 7 8 | # _*_ coding: utf-8 _*_ import socket ip_port = ( '127.0.0.1' , 8989 ) client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) client.sendto( 'hello' .encode( 'utf-8' ),ip_port) client.sendto( 'james' .encode( 'utf-8' ),ip_port) client.close() |
服务端
1 2 3 4 5 6 7 8 9 10 11 | # _*_ coding: utf-8 _*_ import socket ip_port = ( '127.0.0.1' , 8989 ) server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) server.bind(ip_port) res1 = server.recvfrom( 5 ) print ( "res1:" ,res1) res2 = server.recvfrom( 5 ) print ( "res2:" ,res2) server.close() |
12,执行指定的命令,让客户端可以查看服务端的时间
13,执行指定的命令,让客户端可以与服务的的时间同步
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # _*_ coding: utf-8 _*_ import socket import subprocess import time server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.bind(( '127.0.0.1' , 8080 )) while True : data, client_addr = server.recvfrom( 1024 ) print (data, client_addr) obj = subprocess.Popen(data.decode( 'utf-8' ),shell = True , # time 命令在windows 下不能用 stdout = subprocess.PIPE, stderr = subprocess.PIPE) stdout = obj.stdout.read() stderr = obj.stderr.read() print (stdout + stderr) server.sendto(stdout + stderr,client_addr) if data.decode( 'utf-8' ) = = 'time' : str_time = time.strftime( '%Y-%m-%d %H:%M:%S' , time.localtime()) # str_time = '2017-01-01 00:00:00' server.sendto(str_time.encode( 'gbk' ), client_addr) server.close() |
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # _*_ coding: utf-8 _*_ import socket import os import time client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True : msg = input ( '>>>:' ).strip() client.sendto(msg.encode( 'utf-8' ),( '127.0.0.1' , 8080 )) data,server_addr = client.recvfrom( 1024 ) print (data.decode( 'utf-8' ),server_addr) localtime = time.localtime() os.system( "date %d-%d-%d" % (localtime.tm_year, localtime.tm_mon, localtime.tm_mday)) # 设置日期 os.system( "time %d:%d:%d.0" % (localtime.tm_hour, localtime.tm_min, localtime.tm_sec)) # 设置时间 client.close() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步