Python之套接字
Python之套接字
客户端Client/服务端Server架构:
1、硬件C/S架构
2、软件C/S架构
OSI4层:4层里有五层,五层里又有7层。
四层---------五层--------七层
网络接口层 物理层 物理层
网络接口层 数据链路层 数据链路层
网络层 网络层 网络层
传输层 传输层 传输层
应用层 应用层 应用层
表示层
会话层
传输层设备:四层交换机,四层路由器
网络层设备:路由器,三层交换机
数据链路层设备:网桥,以太网交换机,网卡
物理层设备:中继器,集线器,双绞线
Socket层:
什么是Socket:
Socket是应用层与TCP/IP协议通信的中间软件抽象层,他是一组接口,在设计模式中,Socket其实是一个门面模式。它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。所以,无需深入理解tcp/udp协议,socket已经封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
也有人将socket说成ip+port,ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序,ip地址是配置到网卡上的,而port是应用程序开启的,ip与port的绑定就标识了互联网中独一无二的一个应用程序,而程序的pid是同一台机器上不同进程或者线程的标识
套接字分类:
套接字有两种,分别是基于文件型的和基于网络型的。
基于文件类型的套接字家族
套接字家族的名字:AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
基于网络类型的套接字家族
套接字家族的名字:AF_INET
(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)
套接字工作流程:
一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理。
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束
socket()模块函数用法:
- import socket
- socket.socket(socket_family,socket_type,protocal=0)
- socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为 0。
- 获取tcp/ip套接字
- tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- 获取udp/ip套接字
- udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- 由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用 'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。
- 例如tcpSock = socket(AF_INET, SOCK_STREAM)
- 服务端套接字函数
- s.bind() 绑定(主机,端口号)到套接字
- s.listen() 开始TCP监听
- s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来
- 客户端套接字函数
- s.connect() 主动初始化TCP服务器连接
- s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
- 公共用途的套接字函数
- s.recv() 接收TCP数据
- s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
- s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
- s.recvfrom() 接收UDP数据
- s.sendto() 发送UDP数据
- s.getpeername() 连接到当前套接字的远端的地址
- s.getsockname() 当前套接字的地址
- s.getsockopt() 返回指定套接字的参数
- s.setsockopt() 设置指定套接字的参数
- s.close() 关闭套接字
- 面向锁的套接字方法
- s.setblocking() 设置套接字的阻塞与非阻塞模式
- s.settimeout() 设置阻塞套接字操作的超时时间
- s.gettimeout() 得到阻塞套接字操作的超时时间
- 面向文件的套接字的函数
- s.fileno() 套接字的文件描述符
- s.makefile() 创建一个与该套接字相关的文件
- 1:用打电话的流程快速描述socket通信
- 2:服务端和客户端加上基于一次链接的循环通信
- 3:客户端发送空,卡主,证明是从哪个位置卡的
- 服务端:
- from socket import *
- phone=socket(AF_INET,SOCK_STREAM)
- phone.bind(('127.0.0.1',8081))
- phone.listen(5)
- conn,addr=phone.accept()
- while True:
- data=conn.recv(1024)
- print('server===>')
- print(data)
- conn.send(data.upper())
- conn.close()
- phone.close()
- 客户端:
- from socket import *
- phone=socket(AF_INET,SOCK_STREAM)
- phone.connect(('127.0.0.1',8081))
- while True:
- msg=input('>>: ').strip()
- phone.send(msg.encode('utf-8'))
- print('client====>')
- data=phone.recv(1024)
- print(data)
- 说明卡的原因:缓冲区为空recv就卡住,引出原理图
- 4.演示客户端断开链接,服务端的情况,提供解决方法
- 5.演示服务端不能重复接受链接,而服务器都是正常运行不断来接受客户链接的
- 6:简单演示udp
- 服务端
- from socket import *
- phone=socket(AF_INET,SOCK_DGRAM)
- phone.bind(('127.0.0.1',8082))
- while True:
- msg,addr=phone.recvfrom(1024)
- phone.sendto(msg.upper(),addr)
- 客户端
- from socket import *
- phone=socket(AF_INET,SOCK_DGRAM)
- while True:
- msg=input('>>: ')
- phone.sendto(msg.encode('utf-8'),('127.0.0.1',8082))
- msg,addr=phone.recvfrom(1024)
- print(msg)
- udp客户端可以并发演示
- udp客户端可以输入为空演示,说出recvfrom与recv的区别,暂且不提tcp流和udp报的概念,留到粘包去说
Socket实验推演流程
基于TCP的套接字
tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端
tcp服务端
- ss = socket() #创建服务器套接字
- ss.bind() #把地址绑定到套接字
- ss.listen() #监听链接
- inf_loop: #服务器无限循环
- cs = ss.accept() #接受客户端链接
- comm_loop: #通讯循环
- cs.recv()/cs.send() #对话(接收与发送)
- cs.close() #关闭客户端套接字
- ss.close() #关闭服务器套接字(可选)
tcp客户端
- cs = socket() # 创建客户套接字
- cs.connect() # 尝试连接服务器
- comm_loop: # 通讯循环
- cs.send()/cs.recv() # 对话(发送/接收)
- cs.close() # 关闭客户套接字
socket通信流程与打电话流程类似,我们就以打电话为例来实现一个low版的套接字通信
- #_*_coding:utf-8_*_
- __author__ = 'Linhaifeng'
- import socket
- ip_port=('127.0.0.1',9000) #电话卡
- BUFSIZE=1024 #收发消息的尺寸
- s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
- s.bind(ip_port) #手机插卡
- s.listen(5) #手机待机
- conn,addr=s.accept() #手机接电话
- # print(conn)
- # print(addr)
- print('接到来自%s的电话' %addr[0])
- msg=conn.recv(BUFSIZE) #听消息,听话
- print(msg,type(msg))
- conn.send(msg.upper()) #发消息,说话
- conn.close() #挂电话
- s.close() #手机关机
服务端
- #_*_coding:utf-8_*_
- __author__ = 'George'
- import socket
- ip_port=('127.0.0.1',9000)
- BUFSIZE=1024
- s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- s.connect_ex(ip_port) #拨电话
- s.send('linhaifeng nb'.encode('utf-8')) #发消息,说话(只能发送字节类型)
- feedback=s.recv(BUFSIZE) #收消息,听话
- print(feedback.decode('utf-8'))
- s.close() #挂电话
客户端
加上链接循环与通信循环
- #_*_coding:utf-8_*_
- __author__ = 'George'
- import socket
- ip_port=('127.0.0.1',8081)#电话卡
- BUFSIZE=1024
- s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
- s.bind(ip_port) #手机插卡
- s.listen(5) #手机待机
- while True: #新增接收链接循环,可以不停的接电话
- conn,addr=s.accept() #手机接电话
- # print(conn)
- # print(addr)
- print('接到来自%s的电话' %addr[0])
- while True: #新增通信循环,可以不断的通信,收发消息
- msg=conn.recv(BUFSIZE) #听消息,听话
- # if len(msg) == 0:break #如果不加,那么正在链接的客户端突然断开,recv便不再阻塞,死循环发生
- print(msg,type(msg))
- conn.send(msg.upper()) #发消息,说话
- conn.close() #挂电话
- s.close() #手机关机
服务端改进版
- #_*_coding:utf-8_*_
- __author__ = 'George'
- import socket
- ip_port=('127.0.0.1',8081)
- BUFSIZE=1024
- s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- s.connect_ex(ip_port) #拨电话
- while True: #新增通信循环,客户端可以不断发收消息
- msg=input('>>: ').strip()
- if len(msg) == 0:continue
- s.send(msg.encode('utf-8')) #发消息,说话(只能发送字节类型)
- feedback=s.recv(BUFSIZE) #收消息,听话
- print(feedback.decode('utf-8'))
- s.close() #挂电话
客户端改进版
在重启服务端的时候可能会遇到Address already in use的报错。
这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址(如果不懂,请深入研究1.tcp三次握手,四次挥手 2.syn洪水攻击 3.服务器高并发情况下会有大量的time_wait状态的优化方法)
解决方法:
- #加入一条socket配置,重用ip和端口
- phone=socket(AF_INET,SOCK_STREAM)
- phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
- phone.bind(('127.0.0.1',8080))
方法1
- 发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
- vi /etc/sysctl.conf
- 编辑文件,加入以下内容:
- net.ipv4.tcp_syncookies = 1
- net.ipv4.tcp_tw_reuse = 1
- net.ipv4.tcp_tw_recycle = 1
- net.ipv4.tcp_fin_timeout = 30
- 然后执行 /sbin/sysctl -p 让参数生效。
- net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
- net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
- net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
- net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间
方法2
基于UDP的套接字
udp是无链接的,先启动哪一端都不会报错
udp服务端:
- ss = socket() #创建一个服务器的套接字
- ss.bind() #绑定服务器套接字
- inf_loop: #服务器无限循环
- cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送)
- ss.close() # 关闭服务器套接字
udp客户端:
- cs = socket() # 创建客户套接字
- comm_loop: # 通讯循环
- cs.sendto()/cs.recvfrom() # 对话(发送/接收)
- cs.close() # 关闭客户套接字
udp套接字简单示例:
- #_*_coding:utf-8_*_
- __author__ = 'George'
- import socket
- ip_port=('127.0.0.1',9000)
- BUFSIZE=1024
- udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- udp_server_client.bind(ip_port)
- while True:
- msg,addr=udp_server_client.recvfrom(BUFSIZE)
- print(msg,addr)
- udp_server_client.sendto(msg.upper(),addr)
udp服务端
- #_*_coding:utf-8_*_
- __author__ = 'George'
- import socket
- ip_port=('127.0.0.1',9000)
- BUFSIZE=1024
- udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- while True:
- msg=input('>>: ').strip()
- if not msg:continue
- udp_server_client.sendto(msg.encode('utf-8'),ip_port)
- back_msg,addr=udp_server_client.recvfrom(BUFSIZE)
- print(back_msg.decode('utf-8'),addr)
udp客户端
qq聊天(由于udp无连接,所以可以同时多个客户端去跟服务端通信)
- #_*_coding:utf-8_*_
- __author__ = 'George'
- import socket
- ip_port=('127.0.0.1',8081)
- udp_server_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #买手机
- udp_server_sock.bind(ip_port)
- while True:
- qq_msg,addr=udp_server_sock.recvfrom(1024)
- print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],qq_msg.decode('utf-8')))
- back_msg=input('回复消息: ').strip()
- udp_server_sock.sendto(back_msg.encode('utf-8'),addr)
udp服务端
- #_*_coding:utf-8_*_
- __author__ = 'George'
- import socket
- BUFSIZE=1024
- udp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- qq_name_dic={
- '狗哥alex':('127.0.0.1',8081),
- '瞎驴':('127.0.0.1',8081),
- '一棵树':('127.0.0.1',8081),
- '武大郎':('127.0.0.1',8081),
- }
- while True:
- qq_name=input('请选择聊天对象: ').strip()
- while True:
- msg=input('请输入消息,回车发送: ').strip()
- if msg == 'quit':break
- if not msg or not qq_name or qq_name not in qq_name_dic:continue
- udp_client_socket.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
- back_msg,addr=udp_client_socket.recvfrom(BUFSIZE)
- print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],back_msg.decode('utf-8')))
- udp_client_socket.close()
udp客户端1
- #_*_coding:utf-8_*_
- __author__ = 'George'
- import socket
- BUFSIZE=1024
- udp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
- qq_name_dic={
- '狗哥alex':('127.0.0.1',8081),
- '瞎驴':('127.0.0.1',8081),
- '一棵树':('127.0.0.1',8081),
- '武大郎':('127.0.0.1',8081),
- }
- while True:
- qq_name=input('请选择聊天对象: ').strip()
- while True:
- msg=input('请输入消息,回车发送: ').strip()
- if msg == 'quit':break
- if not msg or not qq_name or qq_name not in qq_name_dic:continue
- udp_client_socket.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
- back_msg,addr=udp_client_socket.recvfrom(BUFSIZE)
- print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],back_msg.decode('utf-8')))
- udp_client_socket.close()
udp客户端2
服务端运行结果
客户端1运行结果
客户端2运行结果
时间服务器:
- #_*_coding:utf-8_*_
- __author__ = 'George'
- from socket import *
- from time import strftime
- ip_port=('127.0.0.1',9000)
- bufsize=1024
- tcp_server=socket(AF_INET,SOCK_DGRAM)
- tcp_server.bind(ip_port)
- while True:
- msg,addr=tcp_server.recvfrom(bufsize)
- print('===>',msg)
- if not msg:
- time_fmt='%Y-%m-%d %X'
- else:
- time_fmt=msg.decode('utf-8')
- back_msg=strftime(time_fmt)
- tcp_server.sendto(back_msg.encode('utf-8'),addr)
- tcp_server.close()
ntp服务端
- #_*_coding:utf-8_*_
- __author__ = 'George'
- from socket import *
- ip_port=('127.0.0.1',9000)
- bufsize=1024
- tcp_client=socket(AF_INET,SOCK_DGRAM)
- while True:
- msg=input('请输入时间格式(例%Y %m %d)>>: ').strip()
- tcp_client.sendto(msg.encode('utf-8'),ip_port)
- data=tcp_client.recv(bufsize)
- print(data.decode('utf-8'))
- tcp_client.close()
ntp客户端
练习:
服务端:
- import socket
- phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
- phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
- phone.bind(('127.0.0.1',8080)) #绑定手机卡
- phone.listen(5) #开机 ?5
- print('starting....')
- while True: #链接循环
- conn,addr=phone.accept() #等待电话链接
- print('电话线路是',conn)
- print('客户端的手机号是',addr)
- while True: #通信循环
- try: #应对windows系统
- data=conn.recv(1024) #收消息 ?1024
- if not data:break #linux系统
- print('客户端发来的消息是',data)
- conn.send(data.upper())
- except Exception:
- break
- conn.close()
- phone.close()
服务端
客户端:
- import socket
- phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- phone.connect(('127.0.0.1',8080))
- while True: #通信循环
- msg=input('>>: ').strip()
- if not msg:continue
- phone.send(msg.encode('utf-8'))
- print('has send===========>')
- data=phone.recv(1024)
- print('has recv===========>')
- print(data)
- phone.close()
客户端
传命令:
Server端:
- #买手机
- import socket
- import subprocess
- phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- #绑定电话卡
- ip_port=('127.0.0.1',8080)
- phone.bind(ip_port)
- #开机
- phone.listen(5)
- #等待电话
- #链接循环
- while True:
- conn,addr=phone.accept()
- #通讯循环
- while True:
- try:
- cmd=conn.recv(1024)
- res=subprocess.Popen(cmd.decode('utf-8'),
- shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- conn.send(res.stdout.read())
- conn.send(res.stderr.read())
- except Exception:
- break
- conn.close()
- phone.close()
Server
FTPClient端:
- import socket
- import struct
- import json
- import os
- class MYTCPClient:
- address_family = socket.AF_INET
- socket_type = socket.SOCK_STREAM
- allow_reuse_address = False
- max_packet_size = 8192
- coding='utf-8'
- request_queue_size = 5
- 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:
- self.client_close()
- raise
- def client_connect(self):
- self.socket.connect(self.server_address)
- def client_close(self):
- self.socket.close()
- def run(self):
- while True:
- inp=input(">>: ").strip()
- if not inp:continue
- l=inp.split()
- cmd=l[0]
- if hasattr(self,cmd):
- func=getattr(self,cmd)
- func(l)
- def put(self,args):
- cmd=args[0]
- filename=args[1]
- if not os.path.isfile(filename):
- print('file:%s is not exists' %filename)
- return
- else:
- filesize=os.path.getsize(filename)
- head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}
- print(head_dic)
- head_json=json.dumps(head_dic)
- head_json_bytes=bytes(head_json,encoding=self.coding)
- head_struct=struct.pack('i',len(head_json_bytes))
- self.socket.send(head_struct)
- self.socket.send(head_json_bytes)
- send_size=0
- with open(filename,'rb') as f:
- for line in f:
- self.socket.send(line)
- send_size+=len(line)
- print(send_size)
- else:
- print('upload successful')
- client=MYTCPClient(('192.168.16.114',8080))
- client.run()
FTPClient
Python之套接字的更多相关文章
- Python原始套接字编程
在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_R ...
- Python原始套接字编程-乾颐堂
在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_R ...
- Python Socket套接字编程
Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...
- Python的套接字、IPv4和简单的客户端/服务器编程
#!/usr/bin/env python # -*- coding: utf-8 -*- import socket from binascii import hexlify import sys ...
- python通过套接字来发送接收消息
案例如下: 1.启动一个服务端套接字服务 2.启动一个客户端套接字服务 3.客户端向服务端发送一个hello,服务端则回复一个word,并打印 参考地址:https://www.cnblogs.com ...
- python socket 套接字编程 单进程服务器 实现多客户端访问
服务器: import socket #单进程服务器 实现多客户端访问 IO复用 #吧所有的客户端套接字 放在一个列表里面,一次又一次的便利过滤 server = socket.socket(sock ...
- python UDP套接字通信
UDPserver.py import socket #导入套接字模块 s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # - socket.A ...
- Python Socket套接字
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Un ...
- Python socket套接字通信
一.什么是socket? socket是一个模块, 又称套接字,用来封装 互联网协议(应用层以下的层). 二.为什么要有socket? socket可以实现互联网协议 应用层以下的层 的工作,提高开发 ...
随机推荐
- bzoj 2303: [Apio2011]方格染色【并查集】
画图可知,每一行的状态转移到下一行只有两种:奇数列不变,偶数列^1:偶数列不变,奇数列^1 所以同一行相邻的变革染色格子要放到同一个并查集里,表示这个联通块里的列是联动的 最后统计下联通块数(不包括第 ...
- cmdb客户端服务器信息采集一
#cmdb脚本程序一 #!/usr/bin/python # coding:utf-8 """ 采集机器自身信息 1 主机名 2 内存 3 ip与mac地址 4 cpu信 ...
- CMake学习笔记四:usb_cam的CMakeLists解析
最近在学习cmake,在完整看了<cmake实践>一书后,跟着书上例程敲了跑了一遍,也写了几篇相关读书笔记,算是勉强基本入门了.所以找了usb_cam软件包的CMakeLists.txt来 ...
- 数据结构 - 顺序栈的实行(C语言)
数据结构-顺序栈的实现 1 顺序栈的定义 既然栈是线性表的特例,那么栈的顺序存储其实也是线性表顺序存储的简化,我们简称为顺序栈.线性表是用数组来实现的,对于栈这种只能一头插入删除的线性表来说,用数组哪 ...
- bnu oj 13288 Bi-shoe and Phi-shoe
题目链接: http://www.bnuoj.com/contest/problem_show.php?pid=13288 题目大意: 给出一个n,然后给出n个幸运数([1,m]中不能被m整除的数的数 ...
- 51nod 1213 二维曼哈顿距离最小生成树
1213 二维曼哈顿距离最小生成树 基准时间限制:4 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间 ...
- java中实参与形参的概念
形参: public void fun(形参类型 形参名){ ... } 实参: public static void main(String[] args){ 类 对象名=new 类(); 对象名. ...
- 转如何升级oracle版本?(11.2.0.1至11.2.0.4)
dbua from 11.2,0.2 to 11.2.0.4 need 2hours 升级结果: 步骤名 日志文件名 状态 升级前操作 PreUpgrade.l ...
- C# 判断是否移动设备
/// <summary> /// 判断是否移动设备. /// </summary> /// <returns></returns> public st ...
- c语言-依赖倒转
当一个文件(aa.c文件)依赖于头文件(bb.h)时,如果bb.c编译之后形成的bb.o文件重新编译后,aa.o的文件不需要重新编译 aa.c文件: bb.h文件:对bb.c文件进行声明 bb.c文件 ...