用C语言创建多个用户,实现支持多用户在线的FTP程序(C/S)

1 importjson2 importos3 importshelve4 importstruct5 importsubprocess6

7 from conf importsettings8 from lib importcommon9

10

11 classHandlerRequest:12 """处理用户请求."""

13 max_packet_size = 8192

14 encoding = 'utf-8'

15

16 struct_fmt = 'i'

17 fixed_packet_size = 4

18

19 logger =common.load_my_logging_cfg()20

21 def __init__(self, request, address):22 self.request =request23 self.address =address24

25 self.residual_space_size =None26

27 self.breakpoint_resume =None28

29 self.username =None30 self.user_obj =None31 self.user_current_dir =None32

33 defclient_close(self):34 """关闭客户端连接."""

35 self.request.close()36

37 defhandle_request(self):38 """处理客户端请求."""

39 count =040 while count < 3: #连接循环

41 try:42 ifself.auth():43 #收消息

44 user_dic =self.receive_header()45 action_type = user_dic.get('action_type')46 ifaction_type:47 if hasattr(self, '_%s' %action_type):48 func = getattr(self, '_%s' %action_type)49 func(user_dic)50 else:51 self.send_header(status_code=201)52 #发消息

53 else:54 self.send_header(status_code=200)55 else:56 count += 1

57 self.send_header(status_code=199)58 exceptConnectionResetError:59 break

60 #关闭客户端连接

61 self.logger.info('----连接断开---- ip:%s port:%s' %self.address)62 self.client_close()63

64 defunfinished_file_check(self):65 self.logger.info('#执行unfinished_file_check命令# ip:%s port:%s' %self.address)66

67 if notlist(self.breakpoint_resume.keys()):68 self.send_header(status_code=851)69 return

70

71 #self.breakpoint_resume[file_path] =

72 #{'file_size': _file_size, 'unfinished_file_path': unfinished_file_path, 'file_name': _file_name}

73 msg_list =[]74

75 for index, abs_path in enumerate(self.breakpoint_resume.keys(), 1):76

77 user_path = '/'.join(abs_path.split(self.username)[-1].split(os.sep))78 print('abs_path:', user_path)79 file_name = self.breakpoint_resume[abs_path]['file_name']80 src_file_size = self.breakpoint_resume[abs_path]['file_size']81 unfinished_file_size = os.path.getsize(self.breakpoint_resume[abs_path]['unfinished_file_path'])82 percent = unfinished_file_size / src_file_size * 100

83

84 msg = """

85 数量: %s 文件路径: %s 文件名: %s86 文件原大小: %s字节 未完成的文件大小: %s字节 上传的百分比: %.2f%%87 """ %(index, user_path, file_name, src_file_size, unfinished_file_size, percent)88

89 msg_list.append(msg)90 #msg_dic['/03_函数调用的三种形式.mp4'] = 5772100

91 #msg_dic[user_path] = unfinished_file_size

92 #self.send_header(status_code=850, msg_list=msg_list, msg_dic=msg_dic)

93 self.send_header(status_code=850, msg_list=msg_list)94

95 defauth(self):96 """用户登陆认证."""

97 ifself.user_current_dir:98 returnTrue99

100 #涉及到交叉导入

101 from core importmain102 #收消息

103 auth_dic =self.receive_header()104

105 user_name = auth_dic.get('username')106 user_password = auth_dic.get('password')107 md5_password = common.md5('password', password=user_password)108

109 #print(user_name, user_password, md5_password)

110

111 accounts =main.FTPServer.load_accounts()112 if user_name inaccounts.sections():113 if md5_password == accounts[user_name]['password']:114 self.send_header(status_code=100)115

116 self.username =user_name117 self.user_obj =accounts[user_name]118 self.user_obj['home'] =os.path.join(settings.USER_HOME_DIR, user_name)119 self.user_current_dir = self.user_obj['home']120

121 #print('self.user_obj:', self.user_obj)

122 #print("self.user_obj['home']:", self.user_obj['home'])

123

124 self.residual_space_size =common.conversion_quota(125 self.user_obj['quota']) - common.get_size(self.user_obj['home'])126

127 breakpoint_resume_dir_path = os.path.join(self.user_obj['home'], '.upload')128 if notos.path.isdir(breakpoint_resume_dir_path):129 os.mkdir(breakpoint_resume_dir_path)130 self.breakpoint_resume = shelve.open(os.path.join(breakpoint_resume_dir_path, '.upload.shv'))131 self.unfinished_file_check()132

133 self.logger.info('#认证成功# ip:%s port:%s' %self.address)134 returnTrue135 self.logger.info('#认证失败# ip:%s port:%s' %self.address)136 returnFalse137

138 def_ls(self, cmd_dic):139 """

140 运行dir命令将结果发送到客户端.141 :param cmd_dic: {'path': [], 'action_type': 'ls'}142 或 {'path': ['目录1', '目录2', '目录xxx'], 'action_type': 'ls'}143 或 {'path': ['?'], 'action_type': 'ls'}144 :return: None145 """

146 #print('_ls:', cmd_dic)

147 self.logger.info('#执行ls命令# ip:%s port:%s' %self.address)148

149 #核验路径

150 dir_path =self.verify_path(cmd_dic)151 if notdir_path:152 dir_path =self.user_current_dir153

154 if cmd_dic.get('path') == ['?']: #为用户提供ls /?命令

155 dir_path = '/?'

156

157 sub_obj =subprocess.Popen(158 'dir %s' %dir_path,159 shell=True,160 stderr=subprocess.PIPE,161 stdout=subprocess.PIPE162 )163 stderr_bytes, stdout_bytes =sub_obj.stderr.read(), sub_obj.stdout.read()164 cmd_size = len(stderr_bytes) +len(stdout_bytes)165

166 #发报头

167 self.send_header(status_code=301, cmd_size=cmd_size)168 #发消息

169 self.request.sendall(stderr_bytes)170 self.request.sendall(stdout_bytes)171

172 def_cd(self, cmd_dic):173 """

174 根据用户的目标目录, 改变用户的当前目录的值.175 :param cmd_dic: {'action_type': 'cd', 'path': ['..']}176 或 {'action_type': 'cd', 'path': ['目录1', '目录2', '目录xxx'], }177 :return: None178 Z:\pycharm\开发FTP程序之路\第2次FTP_第四模块作业\FUCK_FTP\server\home\egon\目录1179 """

180 #print('_cd:', cmd_dic)

181 self.logger.info('#执行cd命令# ip:%s port:%s' %self.address)182

183 #核验路径

184 dir_path =self.verify_path(cmd_dic)185 ifdir_path:186 if os.path.isdir(dir_path): #判断用户切换的路径是否存在

187 self.user_current_dir =dir_path188 if dir_path == self.user_obj['home']:189 current_dir = '~'

190 else:191 join_dir = ''.join(dir_path.split('%s' % self.username)[1:])192 current_dir = '/'.join(join_dir.split('\'))193 self.send_header(status_code=400, current_dir=current_dir)194 else:195 self.send_header(status_code=499)196 else:197 self.send_header(status_code=498)198

199 def_mkdir(self, cmd_dic):200 """

201 更具用户的目标目录, 且目录不存在, 创建目录标目录, 生成多层递归目录.202 :param cmd_dic: {'action_type': 'mkdir', 'path': ['目录1']}203 或 {'action_type': 'mkdir', 'path': ['目录2', '目录3', '目录xxx']}204 :return: None205 """

206 #print('_mkdir:', cmd_dic)

207 self.logger.info('#执行mkdir命令# ip:%s port:%s' %self.address)208

209 dir_path =self.verify_path(cmd_dic)210 ifdir_path:211 if not os.path.isdir(dir_path): #判断用户要创建的目录时否存在

212 os.makedirs(dir_path)213 self.send_header(status_code=500)214 else:215 self.send_header(status_code=599)216 else:217 self.send_header(status_code=598)218

219 def_rmdir(self, cmd_dic):220 """

221 更具用户的目标目录, 删除不为空的目录.222 :param cmd_dic: {'path': ['目录1', '目录xxx', '空目录'], 'action_type': 'rmdir'}223 :return: None224 """

225 #print('_rmdir:', cmd_dic)

226 self.logger.info('#执行rmdir命令# ip:%s port:%s' %self.address)227

228 dir_path =self.verify_path(cmd_dic)229 ifdir_path:230 ifos.path.isdir(dir_path):231 ifos.listdir(dir_path):232 self.send_header(status_code=699)233 else:234 os.rmdir(dir_path)235 self.send_header(status_code=600)236 else:237 self.send_header(status_code=698)238 else:239 self.send_header(status_code=697)240

241 def_remove(self, cmd_dic):242 """

243 更具用户的目标文件, 删除该文件244 :param cmd_dic: {'path': ['目录1', '目录xxx', '文件'], 'action_type': 'remove'}245 :return:246 """

247 #print('_remove:', cmd_dic)

248 self.logger.info('#执行remove命令# ip:%s port:%s' %self.address)249 file_path =self.verify_path(cmd_dic)250

251 iffile_path:252 ifos.path.isfile(file_path):253 #判断用户删除的文件是否是要续传的文件, 如果是则先把把续传的记录删除

254 if file_path inself.breakpoint_resume.keys:255 delself.breakpoint_resume[file_path]256 os.remove(file_path)257 self.send_header(status_code=700)258 else:259 self.send_header(status_code=799)260 else:261 self.send_header(status_code=798)262

263 def_resume_upload(self, cmd_dic):264 """

265 860: '您正在继续上传文件, 在您继传之前, 您的目前空间:%s!',266 869: '您选择文件路径中没有要续传的文件, 请核对!',267 :param cmd_dic:268 :return:269 """

270 #print('def _resume_upload ===> cmd_args', cmd_dic)

271 self.logger.info('#执行resume_upload命令# ip:%s port:%s' %self.address)272 self._upload(cmd_dic, resume_upload=True)273

274 def _upload(self, cmd_dic, resume_upload=False):275 """客户端276 800: '你可以上传文件, 在您上传之前, 您的目前空间:%s!',277 801: '上传文件成功, 您上传完后的剩余空间:%s!',278 850: '您的还有为上传完的文件, 是否继续上传!',279 851: '检测您不存在未上传完成的文件!',280 852: '您不能进行续传, 因为该文件是完整文件!',281 860: '您正在继续上传文件, 在您继传之前, 您的目前空间:%s!',282 869: '您选择文件路径中没有要续传的文件, 请核对!',283 894: '您不需要再对本路径下上传文件, 该文件在您的当前路径下已经存在!',284 895: '上传文件失败, md5效验不一致, 部分文件内容在网络中丢失, 请重新上传!',285 896: '上传文件失败, 您的空间不足, 您的上传虚假文件大小, 您的剩余空间:%s!',286 897: '上传文件失败, 您的空间不足, 您的剩余空间:%s!',287 898: '上传文件失败, 上传命令不规范!',288 899: '上传文件必须要有文件的md5值以及文件名!',289 """

290 #print('_upload:', cmd_dic)

291 if notresume_upload:292 self.logger.info('#执行upload命令# ip:%s port:%s' %self.address)293

294 #效验: 897, 898, 899

295 _path, _file_md5, _file_name, _file_size = cmd_dic.get('path'), cmd_dic.get('file_md5'), cmd_dic.get(296 'file_name'), cmd_dic.get('file_size')297 file_path = self.verify_upload_action(cmd_dic, _path=_path, _file_md5=_file_md5, _file_name=_file_name,298

299 _file_size=_file_size)300

301 if resume_upload: #断点续传时执行

302 if not file_path or file_path not inself.breakpoint_resume.keys():303 #869: '您选择文件路径中没有要续传的文件, 请核对!',

304 self.send_header(status_code=869)305 return

306

307 #找到之前未穿完的文件名

308 unfinished_file_path = self.breakpoint_resume[file_path]['unfinished_file_path']309 already_upload_size =os.path.getsize(unfinished_file_path)310

311 #效验成功通知续传信号

312 #860: '您正在继续上传文件, 在您继传之前, 您的目前空间:%s!',

313 self.send_header(status_code=860, residual_space_size=self.residual_space_size,314 already_upload_size=already_upload_size)315

316 total_size = _file_size -already_upload_size317 mode = 'a'

318 else: #正常上传执行

319 if notfile_path:320 return

321

322 #判断用户上传的文件是否重复

323 ifos.path.isfile(file_path):324 #894: '您不需要再对本路径下上传文件, 该文件在您的当前路径下已经存在!',

325 self.send_header(status_code=894)326 return

327 else:328 unfinished_file_path = '%s.%s' % (file_path, 'upload')329

330 #效验成功通知上传信号: 800

331 #800: '你可以上传文件, 在您上传之前, 您的目前空间:%s!',

332 self.send_header(status_code=800, residual_space_size=self.residual_space_size)333

334 total_size =_file_size335 mode = 'w'

336

337 #记录断点的功能: 在服务端用户的路径, 记录文件大小, 加上后缀的路径, 文件名

338 #或再次为未传完的文件记录断点

339 self.breakpoint_resume[file_path] = {'file_size': _file_size, 'unfinished_file_path': unfinished_file_path,340 'file_name': _file_name}341

342 #开始接收文件

343 receive_size =0344 with open(unfinished_file_path, '%sb' %mode) as f:345 while receive_size <346 data_bytes="self.request.recv(self.max_packet_size)347" receive_size f.write>

350 os.rename(unfinished_file_path, file_path)351 #删除记录断点的功能

352 delself.breakpoint_resume[file_path]353

354 #801, 895, 896

355 #效验用户端发送的md5于本次上传完毕的md5值

356 upload_file_md5 = common.md5(encryption_type='file', path=file_path)357 if upload_file_md5 !=_file_md5:358 #print('def _upload ===> upload_file_md5:%s, _file_md5:%s' % (upload_file_md5, _file_md5))

359 #895: '上传文件失败, md5效验不一致, 部分文件内容在网络中丢失, 请重新上传!',

360 self.send_header(status_code=895)361 os.remove(file_path)362 return

363

364 #安全性问题: 再次判断用户是否以假的文件大小来跳出服务端限制的配额

365 if receive_size >self.residual_space_size:366 #896: '上传文件失败, 您的空间不足, 您的上传虚假文件大小, 您的剩余空间:%s!',

367 self.send_header(status_code=896, residual_space_size=self.residual_space_size)368 os.remove(file_path)369 return

370 else:371 self.residual_space_size = self.residual_space_size -receive_size372 #print('def _upload ===> receive_size:', receive_size)

373 #print('def _upload ===> os.path.getsize(file_path)', os.path.getsize('%s' % file_path))

374 #801: '上传文件成功, 您上传完后的剩余空间:%s!',

375 self.send_header(status_code=801, residual_space_size=self.residual_space_size)376

377 def_resume_download(self, cmd_dic):378 self._download(cmd_dic, resume_download=True)379

380 def _download(self, cmd_dic, resume_download=False):381 self.logger.info('#执行download命令# ip:%s port:%s' %self.address)382

383 file_path =self.verify_path(cmd_dic)384 if notfile_path:385 #999: '下载文件失败, 您要下载的文件路径不规范!',

386 self.send_header(status_code=999)387 return

388

389 if notos.path.isfile(file_path):390 #998: '下载文件失败, 您要下载的文件路径不存在!',

391 self.send_header(status_code=998)392 return

393

394 #通知可以开始下载

395 #900: '准备开始下载文件!'.

396 file_name = file_path.split(os.sep)[-1]397 file_size =os.path.getsize(file_path)398 file_md5 = common.md5('file', file_path)399 unfinished_file_size = cmd_dic.get('unfinished_file_size')400 ifresume_download:401 #950: '准备开始续传文件!',

402 self.send_header(status_code=950, file_name=file_name, file_size=file_size, file_md5=file_md5)403 else:404 #900: '准备开始下载文件!'.

405 self.send_header(status_code=900, file_name=file_name, file_size=file_size, file_md5=file_md5)406

407 #打开文件发送给客户端

408 with open(file_path, 'rb') as f:409 ifresume_download:410 f.seek(unfinished_file_size)411 for line inf:412 self.request.sendall(line)413

414 def verify_upload_action(self, cmd_dic, *, _path, _file_name, _file_md5, _file_size):415 """

416 核验上传功能.417 897: '上传文件失败, 您的空间不足, 您的剩余空间:%s!',418 898: '上传文件失败, 上传命令不规范!',419 899: '上传文件必须要有文件的md5值以及文件名!',420 """

421 #_path=['03_函数调用的三种形式.mp4']

422 if _path isNone:423 if _file_name and _file_md5 and_file_size:424 if _file_size >self.residual_space_size:425 #print('def _upload ===> self.residual_space_size:', self.residual_space_size)

426

427 #897: '上传文件失败, 您的空间不足, 您的剩余空间:%s!',

428 self.send_header(status_code=897, residual_space_size=self.residual_space_size)429 returnFalse430 else:431 #Z:pycharm开发FTP程序之路第2次FTP_第四模块作业FUCK_FTPserverhomeegon 3_函数调用的三种形式.mp4

432 file_path =os.path.join(self.user_current_dir, _file_name)433 else:434 #899: '上传文件必须要有文件的md5值以及文件名!',

435 self.send_header(status_code=899)436 returnFalse437 else:438 path =self.verify_path(cmd_dic)439

440 if notpath:441 #898: '上传文件失败, 上传命令不规范!',

442 self.send_header(status_code=898)443 returnFalse444 else:445 #Z:pycharm开发FTP程序之路第2次FTP_第四模块作业FUCK_FTPserverhomeegon 3_函数调用的三种形式.mp4

446 file_path =os.path.join(path, _file_name)447 returnfile_path448

449 defverify_path(self, cmd_dic):450 """

451 核验客户端传过来的路径.452 :param cmd_dic: {'action_type': 'ls', 'path': []}453 或 {'action_type': 'ls', 'path': ['目录1', '目录xxx']}454 或 {action_type': 'cd', 'path': ['目录2', '目录xxx']}455 :return: None456 Z:\pycharm\开发FTP程序之路\第2次FTP_第四模块作业\FUCK_FTP\server\home\egon\目录1457 Z:\pycharm\开发FTP程序之路\第2次FTP_第四模块作业\FUCK_FTP\server\home\egon\目录1458 """

459 #print(cmd_dic)

460 path = cmd_dic.get('path')461 ifpath:462 ifisinstance(path, list):463 for element inpath:464 if notisinstance(element, str):465 path =None466 returnpath467 abspath = os.path.normpath(os.path.join(self.user_current_dir, *path))468 #print('def verify_path() ===> abspath:', abspath)

469 if abspath.startswith(self.user_obj['home']):470 path =abspath471 else:472 path = None #用户目录超出限制

473 else:474 path = None #不是列表类型例: '字符串'

475 else:476 path = None #[]

477 #print('def verify_path() ====> path', path)

478 returnpath479

480 defreceive_header(self):481 """

482 接收客户端数据.483 :return: {'action_type': 'cd', 'path': ['目录1', '目录xxx']}484 """

485 header_bytes =self.request.recv(self.fixed_packet_size)486 request_dic_json_length =struct.unpack(self.struct_fmt, header_bytes)[0]487 #print('request_dic_json_length:', request_dic_json_length)

488 #接收报头

489 request_dic_json =self.request.recv(request_dic_json_length).decode(self.encoding)490 request_dic =json.loads(request_dic_json)491

492 #print('request_dic:', request_dic)

493

494 if notrequest_dic:495 return{}496 #print("def receive_header():", request_dic)

497 returnrequest_dic498

499 def send_header(self, *, status_code, **kwargs):500 """

501 发送数据给客户端.502 :param status_code: 400503 :param kwargs: {'current_dir': '/home/egon/目录1/目录xxx'}504 :return: None505 """

506 #print(status_code)

507 #print(kwargs)

508 from core importmain509

510 response_dic =kwargs511 response_dic['status_code'] =status_code512 response_dic['status_msg'] =main.FTPServer.STATUS_CODE[status_code]513 response_dic.update(kwargs)514

515 response_dic_json_bytes =json.dumps(response_dic).encode(self.encoding)516 response_dic_json_bytes_length =len(response_dic_json_bytes)517 header_bytes =struct.pack(self.struct_fmt, response_dic_json_bytes_length)518

519 #print('header_bytes:', header_bytes)

520

521 #发送报头

522 self.request.sendall(header_bytes)523 #发送json后bytes后的字典response_dic

524 self.request.sendall(response_dic_json_bytes)

346>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442213.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android 代理 wifi热点,android wifi热点默认网关

原贴&#xff1a;https://blog.csdn.net/jingzitakk66/article/details/89146696项目需求&#xff0c;android端创建热点&#xff0c;电脑端连接此热点后用socket实现数据传输&#xff0c;PC端获取网卡时无法判断多网卡情况下哪个IP为需要的IP&#xff0c;所以搜了下&#xff0…

android实现电话功能实验报告,安卓开发实验报告-20210407005833.docx-原创力文档

文档编制序号&#xff1a;[KKIDT-LLE0828-LLETD298-POI08]文档编制序号&#xff1a;[KKIDT-LLE0828-LLETD298-POI08]安卓开发实验报告安卓开发实验报告目录页面跳转长按图标抖动以及显示删除页面跳转功能&#xff1a;通过点击button实现2个activity之间的跳转。1.设置监听器监听…

android matrix 缩放,android – 如何获取任意矩阵的缩放值?

图像按矩阵缩放&#xff1a;Matrix matrix new Matrix();matrix.postScale(...);matrix.postTranslate(...);matrix.postRotate(...);...我希望缩放的图像不会小于原始图像的一半,因此总变焦不应小于0.5.但是怎么做呢&#xff1f;我试图获取矩阵的第一个值来检查&#xff1a;f…

买iphone不买android,为何宁可用4年前的苹果6s,也不买两三千的安卓呢?理由很真实...

在这个信息时代&#xff0c;几乎每个人都离不开手机&#xff0c;手机渗入到了我们生活的方方面面&#xff0c;不管是社交聊天、还是影音娱乐&#xff0c;甚至是办公出行&#xff0c;没有手机&#xff0c;很多人都会寸步难行。全球的智能手机市场竞争处于白热化的阶段&#xff0…

android 仿ios timepicker,android:TimePicker仿照IOS時間選擇器,可自定義選擇器

背景:項目要求寫一個選擇器:不僅僅是單純的時間,還包括自定義部分.搜了很久,搜出來只用一個自定義view.java類,再簡單封裝下的選擇器:貼下源碼:public class PickerView extends View{public static final String TAG "PickerView";/*** text之間間距和minTextSize之…

html5画图作品,8款最佳HTML5绘图工具

HTML5无疑是当前最受宠的一项技术&#xff0c;今天推荐8款HTML5绘图工具&#xff0c;同样惊艳你的眼球!这些绘图工具大多数是用HTML5画布(Canvas)实现的&#xff0c;部分辅以Javascript。对每一个web设计者来说&#xff0c;制图和草绘是他们工作中最喜欢的一件事情了。草绘和制…

vivoiqooz1鸿蒙系统,iQOOZ1评测:vivo新一代性价比神机

【手机中国评测】如果说2019是5G发展的元年&#xff0c;那么2020就是5G技术和终端奋起发力的一年。纵观目前市面上的5G机型我们不难发现&#xff0c;“涨价”已经成为了2020年的新关键词。技术成本的提升&#xff0c;让5G手机似乎失去了我们传统意义上的性价比。但这世间从来不…

html在表格添加下拉按钮,Bootstrap-table 使用说明--如何在表格td里增加一个按钮

如何在表格td里增加一个按钮&#xff1a;如何在列表操作列区域添加按钮初始化表格table.bootstrapTable --》columns 增加&#xff1a;{field: operate, title: __(Operate), table: table,buttons: [{name: detail, text: 详情, title: 详情, icon: fa fa-list, classname: bt…

qt解析html的数据,windows下用QTwebkit解析html

环境windows7 VS2010 QT5.2_opengl配置开发环境1、安装VS20102、安装QT 5.23、安装Visual Studio Add-in for QT54、配置VS 2010配置路径&#xff1a;QT5 > "Qt Options" > "Qt Versions" > Add默认路径为&#xff1a;C:\Qt\Qt5.2.0\5.2.0\msvc…

html缓慢下拉,html - 列表下拉导航-适用于除野生动物园之外的所有浏览器。 间隔开并缓慢 - 堆栈内存溢出...

问题我创建了一个完全由CSS完成的下拉菜单&#xff0c;使用了教程中介绍的绝对定位方法。 效果很好。 在Safari中&#xff0c;它运行缓慢&#xff0c;缓慢&#xff0c;并且链接间隔开。该下拉菜单可在Safari以外的所有浏览器中完美运行。 为什么&#xff1f;HomeAbout UsContac…

计算机网络拓扑图的描述,计算机网络拓扑结构 以下关于星型网络拓扑结构的描述正确的是______。 (多选题 )...

题目和答案在最下面&#xff01;全文转自百度&#xff0c;自己总结方便自己以后查找&#xff01;常见类型&#xff1a;星型拓扑总线拓扑▪ 环型拓扑▪ 树型拓扑▪ 混合型拓▪ 网型拓扑开关电源拓扑简单介绍的&#xff1a;星型优点&#xff1a;可靠性高&#xff0c;方便管理&…

考研生物和计算机结合的专业,2020考研:生物医学工程,考研是考原专业还是跨专业考计算机好?...

中公浙江研招网温馨提醒您关注专业解析&#xff1a;【2020考研&#xff1a;考研想考编程专业但没基础&#xff0c;该怎么准备?】2019浙江考研复试群&#xff1a;8663839642020浙江考研交流群&#xff1a;416469560许多考生在报考专业的时候会很茫然&#xff0c;怕考原专业毕业…

vue项目编写html,从头搭建、编写一个VUE项目

一、创建VUE项目1、新建一个vue项目进入工作目录&#xff0c;新建一个vue项目&#xff1a;vue init webpack 项目名vue init webpack vue-project-demoimage.png说明&#xff1a;Vue build > 打包方式&#xff0c;回车即可&#xff1b;Install vue-router > 是否要安装 v…

nodejs 保存html文件路径,nodejs如何将获得的数据保存到本地?

nodejs将获得的数据保存到本地可以使用Cookie进行数据保存或使用sessionStorage、localStorage进行数据保存。使用Cookie保存Cookie这个恐怕是最常见也是用得最多的技术了&#xff0c;也是比较古老的技术了。Cookie优点很多&#xff0c;使用起来很方便 但它的缺点也很多&#x…

大一的我

emmm&#xff0c;今天开始更新第一篇博客啦&#xff0c;一位ACM新人&#xff0c;请多多关照啦。先上一张ak图片激励一下自己(隐私问题所以码掉一部分) 一会更新一下

html 旋转木马 轮播,JS实现旋转木马式图片轮播效果

本文实例为大家分享了js图片轮播的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下主要html代码&#xff1a;Documentfunction $(id){ return document.getElementById(id);}var js_wrap $("js_wrap");var wrap_slide $("wrap_slide");var wrap…

对short类型,输出结果不一样?

#include<stdio.h> #include<iostream> using namespace std;int main() {short x,y;x-32654; y-1234;short zxy;cout<<z<<endl; //cout << (short)xy<<endl; return 0 ; }至今不明白为什么&#xff0c;&#xff0c;有没有哪位大佬讲一下…

呆在实验室到深夜的小随笔

其实蛮喜欢泡在实验室的感觉。 尤其是晚上&#xff0c;幽静&#xff0c;安心。 切题累了就在桌子上趴一会&#xff0c;起来后伸个懒腰&#xff0c;环视屋内&#xff0c;灯还亮着&#xff0c;键盘的敲击声还时隐时现&#xff0c;还有人在陪着我&#xff0c;真好。 嗯&#xff0c…

计算机应用基础形考作业3Excel,国家开放大学《计算机应用基础》考试与答案形考任务模块3 模块3 Excel 电子表格系统—客观题答案(2020年整理).pptx...

国家开放大学《计算机应用基础》考试与答案形考任务模块3 模块3 Excel 电子表格系统—客观题答案(2020年整理).pptx学 海 无 涯 Excel 2010 上机操作题(共 5 题&#xff0c;4 分/题) 1. 创建如下工作表&#xff0c;并保存为EXLT1.xlsx 文件。,接着完成以下操作&#xff1a; 用填…