您的位置:首页 > 理论基础 > 计算机网络

python3之socket&socketserver网络编程

2018-01-12 15:27 766 查看

1、套接字与套接模块

套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象。它们允许程序接受并进行连接,如发送和接受数据。为了建立通信通道,网络通信的每个端点拥有一个套接字对象极为重要。
套接字为BSD UNIX系统核心的一部分,而且他们也被许多其他类似UNIX的操作系统包括Linux所采纳。许多非BSD UNIX系统(如ms-dos,windows,os/2,mac os及大部分主机环境)都以库形式提供对套接字的支持。
三种最流行的套接字类型是:stream,datagram和raw。stream和datagram套接字可以直接与TCP协议进行接口,而raw套接字则接口到IP协议。但套接字并不限于TCP/IP。

套接字模块是一个非常简单的基于对象的接口,它提供对低层BSD套接字样式网络的访问。使用该模块可以实现客户机和服务器套接字。要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包含的函数和类定义,可生成通过网络通信的程序。

python提供了两个级别访问的网络服务:

  • 低级的网络服务支持基本的socket,它提供了标准的BSD sockets API,可以访问底层操作系统socket接口的全部方法
  • 高级别的网络服务模块socketServer,它提供了服务器中心类,可以简化网络服务器的开发。

2、socket模块方法

socket.
socket
(family = AF_INET,type = SOCK_STREAM,proto = 0,fileno = None )  :使用给定的地址系列,套接字类型和协议号创建一个新套接字

socket.
socketpair
([ family [,type [,proto ] ] ] ):使用给定的地址系列,套接字类型和协议编号构建一对连接的套接字对象

socket.
create_connection
(address [,timeout [,source_address ] ] ):连接到侦听Internet 地址(2元组 )的TCP服务,然后返回套接字对象

socket.
fromfd
(fd,family,type,proto = 0 ):复制文件描述符fd(由文件对象的
fileno()
方法返回的整数 ),并从结果中构建一个套接字对象

socket.
fromshare
(data):从该
socket.share()
 方法获得的数据实例化一个套接字。假设套接字处于阻塞模式。

socket.
SocketType:这是表示套接字对象类型的Python类型对象。这是一样的
type(socket(...))

[code]socket.

getaddrinfo
(host,port,family = 0,type = 0,proto = 0,flags = 0 ):将主机 / 端口参数转换为5元组序列,其中包含创建连接到该服务的套接字的所有必要参数

socket.
getfqdn
([ name ] ):为名称返回完全限定的域名。如果名称被省略或为空,则被解释为本地主机

socket.
gethostbyname
(hostname):将主机名转换为IPv4地址格式。IPv4地址以字符串形式返回

socket.
gethostbyname_ex
(hostname):将主机名转换为IPv4地址格式,扩展接口。返回一个triple ,其中主机名是响应给定ip_address的主要主机名,aliaslist是同一地址的备用主机名(可能为空)列表,ipaddrlist是同一主机上同一接口的IPv4地址列表经常但不总是一个地址)。不支持IPv6名称解析,应该用于IPv4 / v6双栈支持

socket.
gethostname
():返回包含Python解释器当前正在执行的机器的主机名的字符串

socket.
gethostbyaddr
(ip_address ):返回一个triple ,其中hostname是响应给定ip_address的主要主机名,aliaslist是同一地址的备用主机名(可能为空)列表, ipaddrlist是同一个接口的IPv4 / v6地址列表主机(最有可能只包含一个地址)。要找到完全限定的域名,请使用该功能。支持IPv4和IPv6

socket.
getnameinfo
(sockaddr,flags ):将套接字地址sockaddr翻译成2元组。根据标志的设置,结果可以在主机中包含完全限定的域名或数字地址表示。同样,端口可以包含字符串端口名称或数字端口号。
(host, port)

socket.
getprotobyname
(protocolname ):将Internet协议名称(例如,
'icmp'
)转换为适合作为(可选)第三个参数传递给该
socket()
 函数的常量。这通常只需要以“原始”模式(
SOCK_RAW
)打开的套接字; 对于正常的套接字模式,如果协议被省略或为零,则自动选择正确的协议

socket.
getservbyname
(servicename [,protocolname ] ):将Internet服务名称和协议名称转换为该服务的端口号。可选的协议名称,如果有,应该是
'tcp'
或 
'udp'
,否则任何协议将匹配

socket.
getservbyport
(port [,protocolname ] ):将Internet端口号和协议名称转换为该服务的服务名称。可选的协议名称,如果有,应该是
'tcp'
或 
'udp'
,否则任何协议将匹配

socket.
ntohl
(x ):将32位正整数从网络转换为主机字节顺序。在主机字节顺序与网络字节顺序相同的机器上,这是无操作的; 否则,它会执行一个4字节的交换操作。

socket.
ntohs
(x ):将16位正整数从网络转换为主机字节顺序。在主机字节顺序与网络字节顺序相同的机器上,这是无操作的; 否则,它执行一个2字节的交换操作

socket.
htonl
(x )将32位正整数从主机转换为网络字节顺序。在主机字节顺序与网络字节顺序相同的机器上,这是无操作的; 否则,它会执行一个4字节的交换操作。
socket.
htons
(x )将16位正整数从主机转换为网络字节顺序。在主机字节顺序与网络字节顺序相同的机器上,这是无操作的; 否则,它执行一个2字节的交换操作

socket.
inet_aton
(ip_string ):将IPv4地址从点分四字符串格式(例如“123.45.67.89”)转换为32位打包二进制格式,作为长度为4个字符的字节对象。当与使用标准C库的程序进行交谈并且需要类型对象

socket.getdefaulttimeout():返回新套接字对象的默认超时值(秒)(float)。值None表示新的套接字对象没有超时。首次导入套接字模块时,默认为None。

socket.setdefaulttimeout(timeout):为新的套接字对象设置默认的超时值(秒)(float)。首次导入套接字模块时,默认为None。请参阅 settimeout()可能的值和它们各自的含义。

socket.sethostname(name):将机器的主机名称设为名称。OSError如果你没有足够的权利,这将会提高 。

socket.if_nameindex():返回网络接口信息列表(index int,name string)元组。 OSError如果系统调用失败。

socket.if_nametoindex(if_name ):返回接口名称对应的网络接口索引号。 OSError如果没有给定名称的接口存在。

socket.if_indextoname(if_index ):返回接口索引号对应的网络接口名称。 OSError如果没有给定索引的接口存在。

3、socket链接

一般socket建立链接需要六个步骤,其中包括:socket.socket()创建socket对象、s.bind绑定地址到socket对象、s.listen监听地址端口、s.accept阻塞接受链接请求、s.send,s.recv方法处理通信数据、s.close关闭链接。

服务器创建套接字链接:

1)创建socket对象: socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

socket.socket(socket.AF_INET,socket.SOCK_STREAM)使用给定的地址族,套接字类型和协议号来创建一个新套接字.

>>> import socket
#创建TCP socket:
>>> sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#创建UDP socket:
>>> sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

family为指定的地址族:

  socket.AF_UNIX :只能够用于单一的Unix系统进程间通信

  socket.AF_INET :服务器之间的网络通信(ipv4协议的TCP和UDP)ipv4,默认为这个

  socket.AF_INET6 :服务器之间的网络通信ipv6

type为指定的套接字类型:

  socket.SOCK_STREAM :面向连接的TCP,默认为这个

  socket.SOCK_DGRAM :面向非连接的UDP

family和type参数是指定了一个协议,我们也可以使用proto第三个参数来直接指定使用的协议。我们也可以使用socket下的函数getprotobyname('tcp'),来代替IPPTOTO_XX变量.

>>> import socket
>>> socket.getprotobyname('tcp')
6
>>> socket.IPPROTO_TCP
6

proto为指定的协议号,一般为0:

  socket.IPPROTO_TCP  :TCP传输协议

  socket.IPPROTO_UDP   :UDP传输协议

  socket.IPPROTO_ICMP  :ICMP链接

  socket.IPPROTO_IP        :IP链接

  socket.IPPROTO_RAW    :要构建IP头部和要发送的各种协议的头部和数据,包括ip头和协议和数据。

2)socket对象绑定地址及端口

地址必须是一个双元素的元组,包括(host,port)主机名或IP地址+端口号。如果端口号或地址错误将引发socke.error异常。

import socket

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

HostPort = ('127.0.0.1',8898)
s.bind(HostPort)  #绑定地址端口

3)socket对象监听地址端口链接

socket.listen(backlog)

backlog指定了最多连接数,至少为1,接到连接请求后,这些请求必须排队等候连接,如果队列已满,则拒绝请求。

import socket

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_TCP)
HostPort = ('127.0.0.1',8898) s.bind(HostPort) #绑定地址端口 s.listen(5) #监听最多5个连接请求

4)socket.accept对象阻塞等待接受链接

fd, addr = self._accept()  

调用accept方法时,socket会进入‘waiting’阻塞状态,客户请求连接时,方法会建立连接并返回服务器。

accept方法会返回一个含有两个元素的元组,(fd,addr)。第一个元素是新的socket对象,服务器通过它与客户端通信。第二个元素是客户端的地址及端口信息。

import socket

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
HostPort = ('127.0.0.1',8899)
s.bind(HostPort)  #绑定地址端口
s.listen(5)  #监听最多5个连接请求
while True:
print('server socket waiting...')
obj,addr = s.accept()  #阻塞等待链接
print('socket object:',obj)
print('client info:',addr)

#运行,链接输出信息
server socket waiting...
socket object: <socket.socket fd=260, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8899), raddr=('127.0.0.1', 28237)>
client info: ('127.0.0.1', 28237)
server socket waiting...

5)处理阶段,服务器与客户端通过send和recv方法通信(传输数据)

调用新链接对象与客户端或者服务器通信:

socket.recv(buffersize)  :接受客户端信或服务器数据,buffersize指定接收数据的大小,单位为字节。

socket.send(data) :发送信息给客户端或服务器,信息必须转换为字节才能发送。

import socket

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
HostPort = ('127.0.0.1',8899)
s.bind(HostPort)  #绑定地址端口
s.listen(5)  #监听最多5个连接请求
while True:
print('server socket waiting...')
obj,addr = s.accept()  #阻塞等待链接,创建新链接对象(obj)和客户端地址(addr)
while True:
client_data = obj.recv(1024)  #通过新链接对象接受数据
print(client_data)
obj.send(client_data)  #通过新链接对象发送数据

6)传输结束,关闭链接

socket.close()  关闭链接

 

客户端创建套接字链接:

1)s = socket.socket() 创建socket对象

2)s.connect('127.0.0.1','80')  绑定地址端口链接服务器

3)s.send(data)  发送数据到服务器

4)s.recv(1024)  接收服务器数据

5)s.close()  关闭链接

4、socket套接字对象方法

服务器段套接字:

s.bind()  :绑定地址(host,port)到套接字,在AF_INET下,以元组(host,port)的形式表示地址。

s.listen()  :开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。

s.accept()  :被动接受TCP客户端连接,(阻塞式)等待连接的到来

客户端套接字:

s.connect() :主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误

s.connect_ex() :connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数:

s.recv()  :接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。

s.send()  :发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。

s.sendall()  :完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。

s.recvfrom()  :接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

s.sendto()  :发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。

s.close()  :关闭套接字

s.getpeername()  :返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)

s.getsockname()  :返回套接字自己的地址。通常是一个元组(ipaddr,port)

s.setsockopt(level,optname,value)  :设置给定套接字选项的值。

s.getsockopt(level,optname[.buflen])  :返回套接字选项的值。

s.settimeout(timeout)  :设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())

s.gettimeout()  :返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None

s.fileno()  :返回套接字的文件描述符

s.setblocking(flag)  :如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。

s.makefile()  :创建一个与该套接字相关连的文件

5、socket实例

1)简单的TCP socket会话

服务器代码:

import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
HostPort = ('127.0.0.1',8898)
s.bind(HostPort)  #绑定地址端口
s.listen(5)  #监听最多5个连接请求
while True:
print('server socket waiting...')
c,addr = s.accept()  #阻塞等待链接,创建套接字c链接和地址信息addr
while True:
try:
client_date = c.recv(1024) #接收客户端数据
if str(client_date,'utf8') == 'quit':
c.close()
break
except Exception:
break
c.send(client_date)  #发送数据给客户端
print('clientINFO:',str(client_date, 'utf8')) #打印数据,默认接收数据为bytes,需转换成str

此处使用try捕捉异常,是在客户端断开链接时,服务器端会抛出异常,为了实现多连接排队链接,必须捕捉异常让程序正常运行,这种现象只在windows系统下存在;在linux下的表现形式又不同,在linux下不会抛出异常,而是正常接收客户端数据而不会退出,只需要判断客户端数据长度,正常退出急可解决问题。

客户端代码:

import socket
hostport = ('127.0.0.1',8898)
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #创建TCP socket
s.connect(hostport)  #链接套接字

while True:
user_input = input('>>>:').strip()
s.send(bytes(user_input,'utf8')) #发送数据到套接字
if not len(user_input):continue
if user_input == 'quit':
s.close()
break
server_reply = s.recv(1024) #接收套接字数据

print(str(server_reply, 'utf8'))  #打印输出

会话结果:

#首先运行服务器代码,然后运行客户端代码链接服务器

#client output:
>>>:hello python
hello python
>>>:socket network programming
socket network programming
>>>:

#server output:
server socket waiting...
clientINFO: hello python
clientINFO: socket network programming

2)简单的UDP socket会话

服务器接收端:

import socket
HostPort = ('127.0.0.1',7777)
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #创建UDP套接字
sock.bind(HostPort) #服务器端绑定端口

while True:
data,addr = sock.recvfrom(1024) #接收端口数据
print(str(data,'utf8'))  #打印数据

客户端发送端:

import socket
HostPort = ('127.0.0.1',7777)
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
user_input = input('>>>:')
if user_input == 'quit':break
sock.sendto(user_input.encode(),HostPort) #指定地址端口发送数据,数据必须encode
sock.close()

3)socke实现简单版ssh

服务器代码:

import subprocess
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
HostPort = ('192.168.146.129',8821)
s.bind(HostPort)
s.listen(5)
while True:
print('server socket waiting...')
c,addr = s.accept()  #阻塞等待连接,并创建套接字和地址端口对象
while True:
client_date = c.recv(1024)  #接收数据
if not client_date:break  #判断数据为空则跳出循环
if str(client_date,'utf8') == 'quit':  #指定正常退出链接接口
c.close()
break
strule = client_date.decode()  #解码数据
strule_out = subprocess.Popen(strule,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)  #交互系统执行命名,并将输出和错误输出到管道
strule_out_read = strule_out.stdout.read()  #读取管道数据
if not strule_out_read:  #判断命令错误时,数据为错误输出信息
strule_out_read = strule_out.stderr.read()
#在发送数据前,先发送数据长度到客户端并确认
coun =bytes("cmd_result_size|%s" %len(strule_out_read),'utf8')
#print(coun)
c.send(coun)  #发送数据长度

client_ack = c.recv(50)  #接收客户端确认信息
#print(str(client_ack,'utf8'))
if str(client_ack,'utf8') == 'client ready to recv': #确认客户端后开始发送数据
c.send(strule_out_read)
#print(str(strule_out_read,'utf8'))

#print('clientINFO:',str(client_date, 'utf8'))

客户端代码:

import socket
hostport = ('192.168.146.129',8821)
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #创建TCP socket
s.connect(hostport)  #链接套接字

while True:
user_input = input('>>>:').strip()
if not len(user_input):continue
if user_input == 'quit':
s.send(bytes('quit','utf8'))
s.close()
break
else:
s.send(bytes(user_input, 'utf8'))  # 发送数据到套接字
server_ack = s.recv(100)  #接收数据长度
ack_msg = str(server_ack.decode()).split('|')
if ack_msg[0] == "cmd_result_size": #判断是否为数据长度包
ack_size = int(ack_msg[1])  #获取数据长度
s.send('client ready to recv'.encode()) #发送客户端确认信息
tool = 0
count_info = ''
while tool < ack_size:  #判断接收数据长度是否小于总数据长度,则循环接收数据
server_reply = s.recv(1024) #接收套接字数据
count_info +=str(server_reply.decode())
tool += len(server_reply)
else:
print(count_info)  #正常接收完数据后打印

 6、socketserver框架

该socketserver模块简化了编写网络服务器的任务;共有四个基本的具体服务器类:

class socketserver.TCPServer(server_address,RequestHandlerClass,bind_and_activate=True)

class DatagramRequestHandler(BaseRequestHandler):
def setup(self):
from io import BytesIO
self.packet, self.socket = self.request
self.rfile = BytesIO(self.packet)
self.wfile = BytesIO()

def finish(self):
self.socket.sendto(self.wfile.getvalue(), self.client_address)
DatagramRequestHandler

这些

BaseRequestHandler
子类重写 
setup()
finish()
 方法,提供
self.rfile
self.wfile
属性。该
self.rfile
self.wfile
属性可以被读取或写入,分别获得请求的数据或者数据返回给客户端。

 3)socketserver实例

  • socketserver.TCPServer示例:实现同步多并发链接,一个进程只能在处理完一个链接后才能处理第二个链接。

服务器端:

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):
‘‘‘服务器处理请求类程序,每连接一次服务器实例化一次,并重写handle()方法来实现通信客户端’’’
def handle(self):
print('new connection:',self.client_address) #获取客户端地址和端口
while True:
self.data = self.request.recv(1024).strip() #request获取连接客户端的套接字,recv接收客户端数据
print('{}AddrAndPort:'.format(self.client_address))
print(self.data)
self.request.sendall(self.data.upper())  #发送数据到客户端并转换大小写

if __name__ == "__main__":
HOSTPORT = ('127.0.0.1',9988)
#创建服务器,绑定地址端口和类
server = socketserver.TCPServer(HOSTPORT,MyTCPHandler)
#运行服务器,相对于守护进程,直到按ctrl-c来结束程序
server.serve_forever()
  • 使用预定义包装的类ThreadingTCPServer实现异步并发链接:
import socketserver
class Mysocket(socketserver.StreamRequestHandler): #重写setup和finish方法
def handle(self):  #处理链接
print('client:',self.client_address)
while 1:
data = self.request.recv(1024)
self.request.send(data)
print(data.decode())

if __name__ == '__main__':
AddrPort = ('127.0.0.1',7899)
server = socketserver.ThreadingTCPServer(AddrPort,Mysocket) #多线程创建实例链接
server.serve_forever()  #循环接收链接
  • windows系统下的一个bug:
import socketserver
class Mysocket(socketserver.BaseRequestHandler):
def handle(self):
print('client:',self.client_address)
while 1:
data = self.request.recv(1024)
self.request.send(data)
print(data.decode())

if __name__ == '__main__':
AddrPort = ('127.0.0.1',7899)
#如果此处使用ForkingTCPServer类来创建多进程的实例化链接,在windows系统下会报错
server = socketserver.ForkingTCPServer(AddrPort,Mysocket)
server.serve_forever()
#链接后异常:
File "Z:\Program Files\Python35\lib\socketserver.py", line 588, in process_request
pid = os.fork()
AttributeError: module 'os' has no attribute 'fork'
#原因是:
`os.fork` isn't available on Windows
os.fork在windows上是不可用的。
  • 简单版FTPServer:
#服务器代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/1/12 11:02
# @Author  : Py.qi
# @File    : SOCKSERVER_01.py
# @Software: PyCharm

from socketserver import ThreadingTCPServer,StreamRequestHandler
import os,json
host_path = os.getcwd()
class MyHandler(StreamRequestHandler):

def handle(self):
print('clientaddr:',self.client_address)
while True:
try:
data = self.request.recv(1024)
except Exception:
break

if data.decode() == 'ls':   #简单查看目录下的文件
lsdir = os.listdir(os.getcwd())
pi = json.dumps(lsdir)
self.request.send(pi.encode())
if len(data.decode().split()) >= 2:
action, filename = data.decode().split()
print(action,filename)
filename_cd = host_path + '\\' + filename
if action == 'get':
print(action)
self.getfile(filename)
print('getfiel..end')
elif action == 'upt':  #上传交给类方法处理
print(action)
self.uptfile(filename)
print('upt---end')
elif action == 'cd':  #简单cd命令
os.chdir(filename_cd)
lsdir1 = os.listdir(filename_cd)
p2 = json.dumps(lsdir1)
self.request.send(p2.encode())

def getfile(self,filename):  #文件下载
filename_path = host_path + '\\' + filename
print(filename_path)
with open(filename_path,'rb') as f:
filedata = f.read()
self.request.send(filedata)
self.request.close()
def uptfile(self,filename):  #文件上传
self.request.send(bytes('ok','utf8'))
filename_uptfile = host_path + '\\' + filename
with open(filename_uptfile,'wb') as f1:
uptdata = self.request.recv(1024)
f1.write(uptdata)
self.request.close()

if __name__ == "__main__":
hostprot = ('127.0.0.1',5556)
server = ThreadingTCPServer(hostprot,MyHandler)
print('connection to who...')
server.serve_forever()

#客户端代码:

#!/usr/bin/env python
#coding:utf8
#file:Administrator
#time:20180104

import socket,os,json
host_path = r'Z:\\'
hostport = ('127.0.0.1',5556)
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #创建TCP socket
#s.bind(hostport)
s.connect(hostport)  #链接套接字

while True:
user_input = input('>>>:').strip()
s.send(user_input.encode()) #发送数据到套接字
if not len(user_input):continue
if user_input == 'quit':
s.close()
break
server_reply = s.recv(1024) #接收套接字数据
if not server_reply:break
if len(user_input.split()) > 1:
if user_input.split()[0] == 'get':
filename = user_input.split()[1]
filename_path = host_path + filename
with open(filename_path,'wb') as f:
print('----')
f.write(server_reply)
if user_input.split()[0] == 'upt':
#redy = s.recv(1024)
print(server_reply)
filename_u = user_input.split()[1]
filename_u_path = host_path + filename_u
with open(filename_u_path,'rb') as f1:
upt_data = f1.read()
print(upt_data)
s.send(upt_data)
elif len(user_input.split()) == 1:
lsdata = server_reply.decode()
print(lsdata)

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: