Python基础__socket编程

1、计算机网络

1、OSI网络七层模型

OSI模型描述:

1、应用层:一些终端的应用,比如说 ftp、web程序

2、表示层:主要是进行对接受的数据进行解释、加密与解密、压缩与解压缩

3、会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路

4、传输层:定义了一些传输数据的协议和端口号

5、网络层:主要将下层接收的数据进行IP地址的封装与解封装

6、数据链路层:主要将从物理层接收的数据进行MAC地址的封装与解封装

7、物理层:主要定义物理设备标准,如:网线的接口

2、网络通信要素

  1. ip地址

    • 用来表示网络上一台独立的主机
    • ip地址=网络地址+主机地址(网络地址:用于识别主机所在的网络/网段,主机地址:用于识别该网络中的主机)
    • 特殊的ip地址:127.0.0.1(本地回环地址、保留地址),可用于简单的测试网卡是否故障,表示本机
  2. 端口号:

    • 用于表示进程的逻辑地址,不同的进程都有不同的端口标识。
    • 端口:要将数据发送到对方指定的应用程序上,为了标识这些应用程序,所以都给这些网络应用程序都用数字进行标识,为了方便称呼这些数字,则这些数字成为端口。
  3. 传输协议

    • 通讯协议规则:

      • udp:User Datagram Protocol 用户数据协议

        特点:

        1、面向无连接:传输数据之前源端和目的端不需要建立连接。

        2、每个数据报的大小都限制在64k以内

        3、面向报文的不可靠协议(发送出去的数据不一定会接收到)

        4、传输速率快,效率高

        5、应用场景:邮局寄件、实时在线聊天、视频会议。。。

      • tcp:Transmission Control Protocol传输控制协议

        特点:

        1、面向连接:传输数据之前需要建立连接

        2、在连接过程中进行大量的数据传输

        3、通过“三次握手”的方式完成连接,是完全可靠协议

        4、传输速度慢,效率低

3、网络通讯步骤

确定对端ip地址-->确定应用程序端口-->确定通讯协议

简单的来说:发送发利用应用软件将上层的应用程序产生的数据前后加上相应的层标识不断的往下层传输(封包过程),最终到达物理层通过看的见摸得着的物理层设备。

2、socke编程

1、概念理解

要想理解socket,就要先来理解TCP,UDP协议

​ TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何再它们之间传输的标准。

​ 从字面意思来看TCP/IP是TCP和IP协议的合称,但实际上TCP/IP协议是指因特网整个TCP/IP协议族。不同于ISO模型的七个分层,TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中

  • 应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等
  • 传输层:TCP,UDP
  • 网络层:IP,ICMP,OSPF,EIGRP,IGMP
  • 数据链路层:SLIP,CSLIP,PPP,MTU

每一抽象层建立在低一层提供的服务上,并且为高一层提供服务,看起来大概是这样子的

​ 我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,我们经常把socket翻译为套接字,socket是在应用层和传输层(TCP/IP协议族通信)之间的一个抽象层,是一组接口,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。

​ 应用程序两端通过“套接字”向网络发出请求或者应答网络请求。可以把socket理解为通信的把手(hand)

​ socket起源于UNIX,在Unix一切皆文件哲学的思想下,socket是一种"打开—读/写—关闭"模式的实现,服务器和客户端各自维护一个"文件",在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。socket的英文原义是“插槽”或“插座”,就像我们家里座机一样,如果没有网线的那个插口,电话是无法通信的。Socket是实现TCP,UDP协议的接口,便于使用TCP,UDP。

2、socket模块通讯流程

流程描述:

1、服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket

2、服务器为socket绑定ip地址和端口号

3、 服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开

4、 客户端创建socket

5、 客户端打开socket,根据服务器ip地址和端口号试图连接服务器socket

6、 服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直等到客户端返回连接信息后才返回,开始接收下一个客户端连接请求

7、 客户端连接成功,向服务器发送连接状态信息

8、 服务器accept方法返回,连接成功

9、客户端向socket写入信息(或服务端向socket写入信息)

10、 服务器读取信息(客户端读取信息)

11、 客户端关闭

12、 服务器端关闭

# ----------------服务器端-----------------------
import socket
# 创建socket对象
sk = socket.socket()
print(sk)
# 设置创建socket连接的ip地址和端口号
address = ('127.0.0.1',8000) # socket对象绑定ip地址和端口号
sk.bind(address) # 设置监听几个连接
sk.listen(100) #等待连接,阻塞
conn,addr = sk.accept() messsages = conn.recv(1024)
print(str(messsages,'utf-8'))
conn.close()
sk.close() # ----------------客户端-----------------------
import socket # 客户端创建socket对象
sk = socket.socket() address = ('127.0.0.1',8000) # 客户端尝试连接服务器端
sk.connect(address)
messages = input('>>>:') # 连接成功后,发送数据
sk.send(bytes(messages,'utf-8')) sk.close() #----------------编码---------------------
# author:Dman
"""
在python3中传输的类型必须是bytes类型(因为bytes更接近底层,更便于计算机识别) python3.x中只有两种数据类型:
str:unicode
bytes:十六进制
----------------------------
str--->bytes
s='中国'
1、bytes(s,'utf8')
2、s.encode('utf-8') #python3编码(encode)的时候,会把数据转换成bytes类型
---------------------------------
bytes-->str
b = bytes('中国')
str(b,'utf8')
b.decode() ***int类型无法直接转换成bytes类型
""" s = 'hello 中国' # 将str类型转换为bytes类型,两种方式
b = bytes(s, 'utf8')
b1 = s.encode('utf8')
print(b,b1) # 将bytes类型转换成str类型,两种方式
s1 = b1.decode('utf8')
s2 = str(b1,'utf8')
print(s1)
print(s2)

总结:

1、在python3中传输的类型必须是bytes类型(因为bytes更接近底层,更便于计算机识别)

2、python3.x中只有两种数据类型:str和unicode类型


bytes:十六进制 **------------->str--->bytes**
s='中国' 方法一:**bytes(s,'utf8')** 方法二:**s.encode('utf-8')** #python3编码(encode)的时候,会把数据转换成bytes类型 **------------->bytes-->str**
b = bytes('中国')
方法一: **str(b,'utf8')**
方法二: **b.decode()** 备注:int类型无法直接转换成bytes类型

3、socket模块其他相关方法

  1. type=SOCK_STREAM #表示使用tcp

    type = SOCK_DGRAM #表示使用UDP

    family=AF_INET #表示服务器之间的通信(使用ipv4)

    family=AF_INET6 #表示服务器之间的通信(使用ipv6)

    family=AF_UNIX #表示不同unix进程之间的通信

  2. socket模块相关方法

    sk.bind(address)
    
      #s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。
    
    sk.listen(backlog)
    
      #开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
    
          #backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5
    #这个值不能无限大,因为要在内核中维护连接队列 sk.setblocking(bool)   #是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。 sk.accept()   #接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。   #接收TCP 客户的连接(阻塞式)等待连接的到来 sk.connect(address)   #连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 sk.connect_ex(address)   #同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061 sk.close()   #关闭套接字 sk.recv(bufsize[,flag])   #接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。 sk.recvfrom(bufsize[.flag])   #与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。 sk.send(string[,flag])   #将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。 sk.sendall(string[,flag])   #将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 #内部通过递归调用send,将所有内容发送出去。 sk.sendto(string[,flag],address)   #将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。 sk.settimeout(timeout)   #设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s ) sk.getpeername()   #返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。 sk.getsockname()   #返回套接字自己的地址。通常是一个元组(ipaddr,port) sk.fileno()   #套接字的文件描述符

4、socket模块实战场景展示

  1. socket简单通讯,代码展示

    # author:Dman
    # date:2019/3/23
    #-------------服务器端
    import socket
    # 创建socket对象
    sk = socket.socket()
    print(sk)
    # 设置创建socket连接的ip地址和端口号
    address = ('127.0.0.1',8000) # socket对象绑定ip地址和端口号
    sk.bind(address) # 设置监听几个连接
    sk.listen(100) #等待连接,阻塞
    conn,addr = sk.accept() messsages = conn.recv(1024)
    print(str(messsages,'utf-8'))
    sk.close() #---------------客户端------
    import socket # 客户端创建socket对象
    sk = socket.socket() address = ('127.0.0.1',8000) # 客户端尝试连接服务器端
    sk.connect(address)
    messages = input('>>>:') # 连接成功后,发送数据
    sk.send(bytes(messages,'utf-8')) sk.close()
  2. socket实现一个客户端可以一直和服务器进行交互

    # author:Dman
    # date:2019/3/23
    #----------------服务器端----------
    '''
    实现一个用户可以一直和客户端进行交互
    '''
    import socket
    sk = socket.socket() address = ('127.0.0.1',8000)
    sk.bind(address)
    sk.listen(10)
    print('waiting....') while True:
    conn, addr = sk.accept()
    print('%s is connecting and waitting for messages...' % addr[0]) while True:
    try:
    data = conn.recv(1024)
    except Exception as e:
    pass
    if str(data,'utf-8') == 'exit':
    conn.close()
    print('客户端请求关闭连接')
    break
    print(str(data,'utf-8'))
    a = input('>>>')
    conn.send(bytes(a,'utf-8')) sk.close() #--------------客户端-------------
    import socket # 客户端创建socket对象
    sk = socket.socket() address = ('127.0.0.1',8000) # 客户端尝试连接服务器端
    sk.connect(address) while True: messages = input('>>>:')
    # 连接成功后,发送数据
    sk.send(bytes(messages,'utf-8'))
    data = sk.recv(1024)
    print(str(data,'utf-8')) sk.close()
  3. 实现一个服务器和多个客户端进行交互(不是同时进行交互,只是断开一个客户端,服务器可以继续接受其他客户端)

    # author:Dman
    # date:2019/3/23
    # author:Dman
    # date:2019/3/23 #--------------服务器端-------------------
    import socket
    sk = socket.socket() address = ('127.0.0.1',8000)
    sk.bind(address)
    sk.listen(10)
    print('waiting....') while True:
    conn, addr = sk.accept()
    print('%s is connecting and waitting for messages...' % addr[0]) while True:
    try:
    data = conn.recv(1024) #win客户端主动关闭的时候会报错
    if str(data, 'utf-8') == 'exit':
    conn.close()
    print('客户端请求关闭连接')
    break
    print('--------', str(data, 'utf-8'))
    a = input('>>>')
    conn.send(bytes(a, 'utf-8')) #win客户端主动关闭的时候会报错
    except Exception as e:
    conn.close()
    break sk.close() #-----------客户端------------------------
    import socket # 客户端创建socket对象
    sk = socket.socket() address = ('127.0.0.1',8000) # 客户端尝试连接服务器端
    sk.connect(address) while True: messages = input('>>>:')
    # 连接成功后,发送数据
    sk.send(bytes(messages,'utf-8'))
    data = sk.recv(1024)
    print(str(data,'utf-8')) sk.close()
  4. 实现远程执行命令,一个服务器端和多个客户端交互(非同时)

    # author:Dman
    # date:2019/3/23
    # author:Dman
    # date:2019/3/23
    #-----------------------服务器端----------
    '''
    实现远程执行简单命令,客户端可以收到server的命令结果,步骤:
    1、创建socket连接
    2、server可以循环接受socket连接
    3、接受socket的命令
    5、执行命令,发送命令返回结果的大小
    6、接受客户端的ok,解决黏包
    7、开始发送真正的数据。
    '''
    import socket
    import subprocess server = socket.socket()
    server.bind(('127.0.0.1',8000))
    server.listen(10)
    print('服务器启动,等待客户端连接....') while True:
    conn,addr = server.accept()
    print('%s 正在连接...' % addr[0])
    while True:
    try:
    command = conn.recv(1024)
    except Exception:
    print('客户端意外中断。。。')
    break
    if not command:break # 服务器解决发来的命令为空的情况 obj = subprocess.Popen(command.decode('utf8'),shell=True,stdout=subprocess.PIPE)
    # print(obj.stdout.read().decode('gbk'))
    command_bytes_gbk = obj.stdout.read() #结果为win命令提示符的编码,默认命令提示符的编码为gbk
    command_bytes_len = len(command_bytes_gbk)
    print("命令的结果大小为:",command_bytes_len) conn.send(str(command_bytes_len).encode('utf8')) #发送命令结果的大小,给客户端 conn.recv(1024) #解决黏包问题
    conn.sendall(command_bytes_gbk) # 发送命令执行结果 conn.close()
    server.close() #---------------客户端--------------
    """
    实现在远程服务器执行简单命令,并获取命令结果
    1、发送命令给服务器
    2、接受服务器发来命令执行结果的大小
    3、解决服务器黏包问题
    4、循环接受命令执行结果
    """
    import socket client = socket.socket()
    client.connect(('127.0.0.1',8000))
    print('客户端启动...') while True:
    message = input('please input command>>>:').strip()
    # if not message:
    # continue
    client.send(message.encode('utf-8')) # 发送command给服务器 data_byte_len=client.recv(1024) #接受服务器发来的命令执行结果的大小。
    data_int_len = int(data_byte_len.decode('utf-8'))
    print("命令的结果大小为:",data_int_len)
    client.send('ok'.encode('utf-8')) #解决服务器黏包的问题 recevied_data = 0 # 循环开始接受命令
    conten_data = bytes()
    while recevied_data != data_int_len:
    data =client.recv(1024)
    recevied_data += len(data)
    conten_data += data print(conten_data.decode('gbk')) client.close()
  5. 实现上传文件

    # author:Dman
    # date:2019/3/24
    #--------------------服务器端--------------------------------
    """
    实现文件上传
    """
    import socket
    import os server = socket.socket()
    BASE_DIR = os.path.dirname(os.path.abspath(__file__)) server.bind(('127.0.0.1',8000))
    server.listen(10)
    print('waitting for connection...') while True:
    conn, addr = server.accept()
    print('%s is connecting...' % addr[0])
    while True:
    try:
    command = conn.recv(1024)
    except Exception:
    print('客户端意外中断')
    conn.close()
    continue cmd,filename,file_size = str(command,'utf-8').split('|') # 接受命令并进行处理 file_path = os.path.join(BASE_DIR,'file',filename) # 绝对路径拼接 print(file_path) file_size = int(file_size)
    conn.sendall('ok'.encode('utf-8')) has_recevied_length = 0 with open(file_path,'ab') as f:
    while has_recevied_length != file_size:
    data = conn.recv(1024)
    f.write(data)
    has_recevied_length += len(data) print('数据已经保存在 %s' % (os.path.join(BASE_DIR,'file'))) #----------------客户端---------------------------- # author:Dman
    # date:2019/3/24
    import socket
    import os client_conn = socket.socket() client_conn.connect(('127.0.0.1',8000)) BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    print(BASE_DIR) while True:
    inp = input(">>>: ").strip()
    cmd,path = inp.split('|') file_path = os.path.join(BASE_DIR,'file',path) #获取绝对文件路径
    filename = os.path.basename(file_path) #获取文件名 file_size = os.stat(file_path).st_size #获取文件大小
    file_info = '%s|%s|%s' % (cmd,filename,file_size)
    client_conn.sendall(file_info.encode('utf-8')) client_conn.recv(1024) has_sent_length = 0 with open(file_path, 'rb') as f:
    while has_sent_length != file_size:
    data = f.read(1024) # 每次读取1024个字节
    client_conn.sendall(data)
    has_sent_length +=len(data) print('上传成功')

3、socketserver模块

1、模块介绍

  • socketserver模块可以简化网络服务器的编写,Python把网络服务抽象成两个主要的类,一个是Server类,用于处理连接相关的网络操作,另外一个则是RequestHandler类,用于处理数据相关的操作。并且提供两个MixIn 类,用于扩展 Server,实现多进程或多线程。

  • Server类:它包含了五种server类,BaseServer、TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer。

    BaseServer:socketserver中服务类的基类

    TCPServer:使用TCP协议,该协议在客户端和服务器之间提供连续数据流。

    UDPServer:使用UDP协议,这些数据包在传输过程中可能无序到达或丢失的信息包,参数与TCPServer一样

    UnixStreamServer和UnixDatagramServer:这些不经常使用的类似于TCP和UDP,但使用Unix域套接字,它们在非Unix平台上不可用。参数与TCPServer相同。

    总结 :这五个server类的继承关系如下:

  • RequestHandler类:需要自己去写,必须继承BaseRequestHandler父类,下面是BaseRequestHandler类的源码:

    class BaseRequestHandler:
    
        """Base class for request handler classes.
    
        This class is instantiated for each request to be handled.  The
    constructor sets the instance variables request, client_address
    and server, and then calls the handle() method. To implement a
    specific service, all you need to do is to derive a class which
    defines a handle() method. The handle() method can find the request as self.request, the
    client address as self.client_address, and the server (in case it
    needs access to per-server information) as self.server. Since a
    separate instance is created for each request, the handle() method
    can define arbitrary other instance variariables. """ def __init__(self, request, client_address, server):
    self.request = request
    self.client_address = client_address
    self.server = server
    self.setup()
    try:
    self.handle()
    finally:
    self.finish() def setup(self):
    pass def handle(self):
    pass def finish(self):
    pass

2、socketserver模块使用步骤:

1、First, you must create a request handler class by subclassing the BaseRequestHandlerclass and overriding its handle() method; this method will process incoming requests.   

2、Second, you must instantiate one of the server classes, passing it the server’s address and the request handler class.

3、Then call the handle_request() orserve_forever() method of the server object to process one or many requests.

4、Finally, call server_close() to close the socket.

另外要想socket实现并发效果,必须使用下面的类

#实现多进程
class socketserver.ForkingTCPServer
class socketserver.ForkingUDPServer
# 实现多线程
class socketserver.ThreadingTCPServer
class socketserver.ThreadingUDPServer
  • 代码实例:

    # author:Dman
    # date:2019/3/25 #----------------服务端-----------------------
    """
    使用socketserver实现一个多并发的服务端
    1、继承BaseRequestHandler,实现handle方法
    2、在handle方法中去实现我们要处理的业务逻辑
    3、创建ThreadingTCPServer实例
    4、调用serve_forever()方法。 """ import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self):
    print ("服务端启动...")
    while True:
    conn = self.request # connection
    print (self.client_address)
    while True:
    client_data=conn.recv(1024)
    print (str(client_data,"utf8"))
    print ("waiting...")
    server_response = input('>>>')
    conn.sendall(server_response.encode('utf-8'))
    conn.close() if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8091),MyServer)
    # print()
    server.serve_forever() #----------------客户端---------------------
    import socket
    ip_port = ('127.0.0.1',8091)
    sk = socket.socket() sk.connect(ip_port)
    print ("客户端启动:")
    while True:
    inp = input('>>>')
    sk.sendall(bytes(inp,"utf8"))
    if inp == 'exit':
    break
    server_response=sk.recv(1024)
    print (str(server_response,"utf8")) sk.close()

4、思考

1、udp和tcp的区别

tcp需要三次握手,每次收到数据,都要发送应答,UDP不需要关心这些。

2、粘包的处理

在两次send之间加一个recv,这样去解决。这样就会把所有数据都从缓冲区先全部发走,在发送别的。

py基础__socket编程的更多相关文章

  1. python 基础网络编程2

    python 基础网络编程2 前一篇讲了socketserver.py中BaseServer类, 下面介绍下TCPServer和UDPServer class TCPServer(BaseServer ...

  2. python 基础网络编程1

    python 基础网络编程1 Source code: Lib/socketserver.py lib的主目录下有一个sockserver.py文件, 里面是python基本的网络编程模型 共有一个b ...

  3. python基础-函数式编程

    python基础-函数式编程  高阶函数:map , reduce ,filter,sorted 匿名函数:  lambda  1.1函数式编程 面向过程编程:我们通过把大段代码拆成函数,通过一层一层 ...

  4. python基础——面向对象编程

    python基础——面向对象编程 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的 ...

  5. [Python] 文科生零基础学编程系列二——数据类型、变量、常量的基础概念

    上一篇:[Python] 文科生零基础学编程系列--对象.集合.属性.方法的基本定义 下一篇: (仍先以最简单的Excel的VBA为例,语法与Python不同,但概念和逻辑需要理解透彻) p.p1 { ...

  6. [Python] 文科生零基础学编程系列三——数据运算符的基本类别

    上一篇:[Python] 文科生零基础学编程系列二--数据类型.变量.常量的基础概念 下一篇: ※ 程序的执行过程,就是对数据进行运算的过程. 不同的数据类型,可以进行不同的运算, 按照数据运算类型的 ...

  7. java基础-网络编程(Socket)技术选型入门之NIO技术

    java基础-网络编程(Socket)技术选型入门之NIO技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传统的网络编程 1>.编写socket通信的MyServer ...

  8. 大数据技术之_16_Scala学习_04_函数式编程-基础+面向对象编程-基础

    第五章 函数式编程-基础5.1 函数式编程内容说明5.1.1 函数式编程内容5.1.2 函数式编程授课顺序5.2 函数式编程介绍5.2.1 几个概念的说明5.2.2 方法.函数.函数式编程和面向对象编 ...

  9. 计算机基础之编程 + 基本组成 + 组成补充 + 操作系统(day01整理)

    目录 一 计算机基础之编程 (一) 什么是编程语言 (二) 什么是编程 (三) 为什么要编程 二 计算机的基本组成 (一) CPU(大脑) (1) 控制器 (2) 运算器 (二) 存储器(记忆) (1 ...

随机推荐

  1. 移动端App开发 - 01 - 开篇

    移动端App开发 - 01 - 开篇 从此笔记之后开启移动端 app 开发学习 该系列笔记去掉所有无关重要的东西,简介干练 我的移动端App开发笔记 1.移动端App开发 - 02 - iPhone/ ...

  2. 对View的onMeasure()方法的进一步研究

    在Android开发中,很多人对自定义View是望而生畏,但这又是向高级进阶的必经之路,主要是对View里面的很多方法不知道怎么理解,其中一个就是onMeasure()方法. 首先,我自定义一个MyV ...

  3. mac下 IDEA 的pom下 出现 Cannot access in offline mode 问题

    在mac下 配置完maven后发现总是不能引入最新的jar包,google了好久总算找到解决办法: 默认带有work offline ,不清楚这个是干嘛用的.勾选掉 了就行了.

  4. LeetCode5 最长回文子串

    最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" ...

  5. LED相关

    P10 模组   分辨率32*16   尺寸320*160      间距 10mm P8 模组   分辨率32*16   尺寸256*128        间距 8mm P7.62 模组   分辨率 ...

  6. 用Easing函数实现碰撞效果

    用Easing函数实现碰撞效果 工程中需要的源码请从这里下载: https://github.com/YouXianMing/EasingAnimation 源码: // // ViewControl ...

  7. 文件复制(shutil)

    import shutil #拷贝整个目录树 shutil.copytree('d:\\aaa','e:\\aaa') #目标文件夹(e:\aaa)必须不存在 shutil.rmtree('e:\\a ...

  8. VC listBox控件的方法

    获取listBox里所有行数 GetCount(); 设置某行的选中状态 SetSel(index,true);第一个参数是行号,第二个参数是否选中

  9. CopyrightHelper—开源VS插件辅助插入版权注释

    前言 有很多时候,我们在写代码的时候需要在代码文件头加上描述和版权信息等,如果使用代码项目模板又得为每种文件定模板,而已不方便,如果从某个地方复制过来,又嫌麻烦... 为了能解决这种懒人的需求,我开始 ...

  10. java万年历

    import java.util.Scanner; public class perpetualCalendar { public static void main(String[] args) { ...