import subprocessres = subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
print('Stdout:',res.stdout.read().decode('gbk'))
print('Stderr:',res.stderr.read().decode('gbk'))

PIPE把输出的东西装到一个'水管'里,如果在windows中的编码格式是gbk,执行结果:

Stdout:  驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录2019/09/16  13:48    <DIR>          .
2019/09/16  13:48    <DIR>          ..
2019/09/16  13:47    <DIR>          .idea
2019/09/16  13:46                21 Client1.py
2019/09/16  13:42                 0 Client2.py
2019/09/16  13:48               207 Sever1.py
2019/09/16  01:41                70 time_test.py
2019/09/14  23:51    <DIR>          venv4 个文件            298 字节4 个目录 45,863,636,992 可用字节Stderr: 

在这里也可以使用os.popen()但是它会不管正确和错误的结果都放在一起,而用subprocess能够分别拿到正确和错误的信息

基于TCP实现的黏包

Sever:

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8092))
sk.listen()
conn,addr = sk.accept()
while True:cmd = input('<<<')conn.send(cmd.encode('gbk'))ret = conn.recv(1024).decode('gbk')print(ret)
conn.close()
sk.close()

Client:

import socket
import subprocess
sk = socket.socket()
sk.connect(('127.0.0.1',8092))
while True:cmd = sk.recv(1024).decode('gbk')ret = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)std_out = 'stdout:' + (ret.stdout.read()).decode('gbk')std_err = 'stderr:' + (ret.stderr.read()).decode('gbk')print(std_out)print(std_err)sk.send(std_out.encode('gbk'))sk.send(std_err.encode('gbk'))
sk.close()

执行结果:

Sever:

<<<dir;ls
stdout: 驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录<<<ipconfig
stderr:找不到文件<<<

Client:

stdout: 驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录stderr:找不到文件stdout:
Windows IP 配置以太网适配器 Bluetooth 网络连接 2:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 本地连接:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 无线局域网适配器 无线网络连接:连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::8c6:36a9:6fa6:8018%14IPv4 地址 . . . . . . . . . . . . : 192.168.43.216子网掩码  . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . : 192.168.43.1隧道适配器 本地连接* 3:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : stderr:

当我们在sever端输入dir;ls命令时,只有stdout的结果跑出来,而当我们输入ipconfig这个命令时,系统将上一次dir;ls未执行完的stderr的结果给跑出来。像这样没有接受完全或者接受多了的就是黏包现象。

TCP会有黏包现象但是它不丢包。

基于UDP实现的黏包

Sever:

import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',8092))
msg,addr = sk.recvfrom(10240)while 1:cmd = input('<<<')if cmd == 'q':breaksk.sendto(cmd.encode('gbk'),addr)msg,addr = sk.recvfrom(10240)print(msg.decode('gbk'))sk.close()

Client:

import socket
import subprocess
sk = socket.socket(type=socket.SOCK_DGRAM)
addr = ('127.0.0.1',8092)
sk.sendto('Start'.encode('utf-8'),addr)
while 1:cmd,addr = sk.recvfrom(10240)ret = subprocess.Popen(cmd.decode('gbk'),shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)std_out = 'Stdout:' + (ret.stdout.read()).decode('gbk')std_err = 'Stderr:' + (ret.stderr.read()).decode('gbk')print(std_out)print(std_err)sk.sendto(std_out.encode('gbk'),addr)sk.sendto(std_err.encode('gbk'),addr)
sk.close()

执行结果:

Sever:

<<<dir;ls
Stdout: 驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录<<<dir
Stderr:找不到文件<<<ipconfig
Stdout: 驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录2019/09/16  14:43    <DIR>          .
2019/09/16  14:43    <DIR>          ..
2019/09/16  14:37    <DIR>          .idea
2019/09/16  14:43               553 Client1.py
2019/09/16  13:42                 0 Client2.py
2019/09/16  14:43               306 Sever1.py
2019/09/16  01:41                70 time_test.py
2019/09/14  23:51    <DIR>          venv4 个文件            929 字节4 个目录 45,855,449,088 可用字节<<<pwd
Stderr:
<<<ip
Stdout:
Windows IP 配置以太网适配器 Bluetooth 网络连接 2:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 本地连接:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 无线局域网适配器 无线网络连接:连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::8c6:36a9:6fa6:8018%14IPv4 地址 . . . . . . . . . . . . : 192.168.43.216子网掩码  . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . : 192.168.43.1隧道适配器 本地连接* 3:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : <<<

Client:

Stdout: 驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录Stderr:找不到文件Stdout: 驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录2019/09/16  14:43    <DIR>          .
2019/09/16  14:43    <DIR>          ..
2019/09/16  14:37    <DIR>          .idea
2019/09/16  14:43               553 Client1.py
2019/09/16  13:42                 0 Client2.py
2019/09/16  14:43               306 Sever1.py
2019/09/16  01:41                70 time_test.py
2019/09/14  23:51    <DIR>          venv4 个文件            929 字节4 个目录 45,855,449,088 可用字节Stderr:
Stdout:
Windows IP 配置以太网适配器 Bluetooth 网络连接 2:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 本地连接:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 无线局域网适配器 无线网络连接:连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::8c6:36a9:6fa6:8018%14IPv4 地址 . . . . . . . . . . . . : 192.168.43.216子网掩码  . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . : 192.168.43.1隧道适配器 本地连接* 3:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : Stderr:
Stdout:
Stderr:'pwd' 不是内部或外部命令,也不是可运行的程序
或批处理文件。Stdout:
Stderr:'ip' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

可以看出UDP不会有黏包现象,会产生丢包现象,没发完就不发了,不完整也不可靠。

黏包成因

TCP协议的数据传送

拆包机制

当发送端缓冲区的长度大于网卡的MTU时,TCP会将这次发送的数据拆成几个数据包发送出去。MTU是Maximum Transmission Unit的缩写,意思是网络上传送最大数据包,MTU是字节单位,大部分网络设备的MTU都是1500.如果本机的MTU比网关的MTU大,大的数据包就会被拆开来传送,这样会产生很多数据包碎片,增加丢包率,降低网络速度。

在正常情况下它的拆包可理解为:

面向流的通信特点和Nagle算法

TCP(transport control protocol,传输控制协议),是面向连接的,面向流的,提供高可靠性的服务。收发两端(客户端和服务端)都要有一一成对的socket,因此发送端为了将多个发往接收端的包,更有效地发往对方,使用了优化算法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样接收端就难于分辨出来了,必须提供科学的拆包机制。即面向流的通信是无消息保护边界的。

对于空消息:TCP是基于数据流的,于是收发消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,而UDP协议是基于数据报的,即便是你输入的是空内容(直接回车),也可以被发送,UDP协议会帮你封装上消息然后发出去。

可靠黏包的TCP协议:TCP协议数据不会丢,没有收完包,就会下次接收,会继续上次继续接受。

基于tcp协议特点的黏包现象成因

当我们在socket服务端发送值1、2,然后根据优化算法,它会把1先放到这个缓存当中等一等,然后再把2一起封装起来,然后再发出去,因此我们看到的就是黏包现象

这种现象的表面现象是两个send太近且发送的消息太短

发送端可以使1K1K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据。也就是说,应用程序所看到的数据是一个整体,或者说是一个流(stream),一条消息有多少字节对应程序是不可见的,因此TCP协议是面向流的协议,这也是容易出现黏包问题的原因。而UDP协议是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的。

解决黏包的方法

解决方案一:

Sever:

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()while True:cmd = input('<<<')if cmd == 'q':conn.send(b'q')breakconn.send(cmd.encode('gbk'))num = conn.recv(1024).decode('utf-8')conn.send(b'ok')res = conn.recv(int(num)).decode('gbk')print(res)conn.close()
sk.close()

Client:

import socket
import subprocesssk = socket.socket()
sk.connect(('127.0.0.1',8080))
while True:cmd = sk.recv(1024).decode('gbk')if cmd == 'q':breakres = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)std_out = res.stdout.read()std_err = res.stderr.read()sk.send(str(len(std_out) + len(std_err)).encode('utf-8'))sk.recv(1024)print('Stdout:' + std_out.decode('gbk'))print('Stderr:' + std_err.decode('gbk'))sk.send(std_out)sk.send(std_err)sk.close()

执行结果:

Sever:

<<<dir驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录2019/09/17  15:33    <DIR>          .
2019/09/17  15:33    <DIR>          ..
2019/09/17  15:31    <DIR>          .idea
2019/09/17  15:33               623 Client1.py
2019/09/16  13:42                 0 Client2.py
2019/09/17  15:21               389 Sever1.py
2019/09/16  01:41                70 time_test.py
2019/09/14  23:51    <DIR>          venv4 个文件          1,082 字节4 个目录 45,031,833,600 可用字节<<<ls
'ls' 不是内部或外部命令,也不是可运行的程序
或批处理文件。<<<ipconfigWindows IP 配置以太网适配器 Bluetooth 网络连接 2:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 本地连接:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 无线局域网适配器 无线网络连接:连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::8c6:36a9:6fa6:8018%14IPv4 地址 . . . . . . . . . . . . : 192.168.43.216子网掩码  . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . : 192.168.43.1隧道适配器 本地连接* 3:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : <<<

Client:

Stdout: 驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录2019/09/17  15:33    <DIR>          .
2019/09/17  15:33    <DIR>          ..
2019/09/17  15:31    <DIR>          .idea
2019/09/17  15:33               623 Client1.py
2019/09/16  13:42                 0 Client2.py
2019/09/17  15:21               389 Sever1.py
2019/09/16  01:41                70 time_test.py
2019/09/14  23:51    <DIR>          venv4 个文件          1,082 字节4 个目录 45,031,833,600 可用字节Stderr:
Stdout:
Stderr:'ls' 不是内部或外部命令,也不是可运行的程序
或批处理文件。Stdout:
Windows IP 配置以太网适配器 Bluetooth 网络连接 2:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 本地连接:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 无线局域网适配器 无线网络连接:连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::8c6:36a9:6fa6:8018%14IPv4 地址 . . . . . . . . . . . . : 192.168.43.216子网掩码  . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . : 192.168.43.1隧道适配器 本地连接* 3:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : Stderr:

这种写法的好处就是能确定Sever到底要接受多少数据,不好的地方就是多了一次交互

解决方案二:使用struct模块

用struct模块我们能把一个数据类型转换成固定长度的bytes

这里以数字类型举例,'i'代表int类型:

import struct
print(struct.pack('i',2048),len(struct.pack('i',2048)))         #b'\x00\x08\x00\x00'    4
print(struct.pack('i',204800),len(struct.pack('i',204800)))     #b'\x00 \x03\x00'       4
print(struct.pack('i',2048000),len(struct.pack('i',2048000)))   #b'\x00@\x1f\x00'       4

当后面的数值戳过一定范围的时候程序就会报错

Sever:

import socket
import struct
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()while True:cmd = input('<<<')if cmd == 'q':conn.send(b'q')breakconn.send(cmd.encode('gbk'))num = conn.recv(4)num = struct.unpack('i',num)[0]res = conn.recv(int(num)).decode('gbk')print(res)conn.close()
sk.close()

Client:

import socket
import subprocess
import structsk = socket.socket()
sk.connect(('127.0.0.1',8080))
while True:cmd = sk.recv(1024).decode('gbk')if cmd == 'q':breakres = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)std_out = res.stdout.read()std_err = res.stderr.read()len_num = len(std_out) + len(std_err)num_by = struct.pack('i',len_num)print('Stdout:' + std_out.decode('gbk'))print('Stderr:' + std_err.decode('gbk'))sk.send(num_by)sk.send(std_out)sk.send(std_err)sk.close()

执行结果:

<<<dir驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录2019/09/17  16:25    <DIR>          .
2019/09/17  16:25    <DIR>          ..
2019/09/17  16:23    <DIR>          .idea
2019/09/17  16:25               659 Client1.py
2019/09/16  13:42                 0 Client2.py
2019/09/17  16:22               400 Sever1.py
2019/09/17  16:08               288 time_test.py
2019/09/14  23:51    <DIR>          venv4 个文件          1,347 字节4 个目录 45,025,951,744 可用字节<<<configip
'configip' 不是内部或外部命令,也不是可运行的程序
或批处理文件。<<<ipconfigWindows IP 配置以太网适配器 Bluetooth 网络连接 2:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 本地连接:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 无线局域网适配器 无线网络连接:连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::8c6:36a9:6fa6:8018%14IPv4 地址 . . . . . . . . . . . . : 192.168.43.216子网掩码  . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . : 192.168.43.1隧道适配器 本地连接* 3:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : <<<

Sever执行结果

Stdout: 驱动器 C 中的卷是 系统卷的序列号是 85C0-669AC:\Users\Administrator\PycharmProjects\Internet_program 的目录2019/09/17  16:25    <DIR>          .
2019/09/17  16:25    <DIR>          ..
2019/09/17  16:23    <DIR>          .idea
2019/09/17  16:25               659 Client1.py
2019/09/16  13:42                 0 Client2.py
2019/09/17  16:22               400 Sever1.py
2019/09/17  16:08               288 time_test.py
2019/09/14  23:51    <DIR>          venv4 个文件          1,347 字节4 个目录 45,025,951,744 可用字节Stderr:
Stdout:
Stderr:'configip' 不是内部或外部命令,也不是可运行的程序
或批处理文件。Stdout:
Windows IP 配置以太网适配器 Bluetooth 网络连接 2:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 本地连接:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : 无线局域网适配器 无线网络连接:连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::8c6:36a9:6fa6:8018%14IPv4 地址 . . . . . . . . . . . . : 192.168.43.216子网掩码  . . . . . . . . . . . . : 255.255.255.0默认网关. . . . . . . . . . . . . : 192.168.43.1隧道适配器 本地连接* 3:媒体状态  . . . . . . . . . . . . : 媒体已断开连接特定的 DNS 后缀 . . . . . . . : Stderr:

Client执行结果

实现一个大文件的传输和下载

当我们在网络上传输所有数据时,这些数据都叫数据包,数据包里的所有数据都叫报文,报文里不止有你的数据还有IP地址、MAC地址、端口号等,所有的报文都有报头,这是由协议规定的。所有在网络上传播数据包的协议里都有一个报头。什么时候需要自己定制报文?比如说复杂的应用上就会应用到、传输文件的时候(文件名、文件大小、文件类型、存储路径等)...

其实在网络传输的过程当中处处有协议,协议就是一堆报头和报文(都由字节组成)。

Sever:

import socket
import struct
import json
buffer = 1024
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()conn,addr = sk.accept()head_len = conn.recv(4)
struct.unpack('i',head_len)[0]
json_head = conn.recv(head_len).decode('utf-8')
head = json.loads(json_head)
file_size = head['fileSize']with open(r'dir\%s'%head['fileName'],'wb') as f:while file_size:if file_size >= buffer:content = conn.recv(buffer)f.write(content)file_size -= bufferelse:content = conn.recv(buffer)f.write(content)break
conn.close()
sk.close()

Client:

import socket
import struct
import os
import jsonsk = socket.socket()
sk.connect(('127.0.0.1',8080))
buffer = 1024
head = {'filePath' : r'C:\Users\Administrator\Desktop\专题\海報資料夾\专题海报','fileName' : r'专题海报','fileSize' : None}
file_path = os.path.join(head['filePath'],head['fileName'])
file_size = os.path.getsize(file_path)head['fileSize'] = file_size
json_head = json.dumps(head)                            #字典转成字典
bytes_head = json_head.encode('utf-8')                  #字符串转bytes

head_len = len(bytes_head)                              #报头的长度
pack_len = struct.pack('i',head_len)sk.send(pack_len)                                       #先发报头的长度
sk.send(bytes_head)                                     #再发bytes类型的报头
with open(r'dir\%s'%file_path,'rb') as f:while file_size:if file_size >= buffer:content = f.read(buffer)  # 每次文件读出的内容
                        sk.send(content)file_size -= bufferelse:content = f.read(file_size)sk.send(content)break
sk.close()

转载于:https://www.cnblogs.com/Fantac/p/11527758.html

Python学习日记(三十一) 黏包问题相关推荐

  1. Python学习日记(三十四) Mysql数据库篇 二

    外键(Foreign Key) 如果今天有一张表上面有很多职务的信息 我们可以通过使用外键的方式去将两张表产生关联 这样的好处能够节省空间,比方说你今天的职务名称很长,在一张表中就要重复的去写这个职务 ...

  2. Python学习日记(三十三) Mysql数据库篇 一

    背景 Mysql是一个关系型数据库,由瑞典Mysql AB开发,目前属于Oracle旗下的产品.Mysql是目前最流行的关系型数据库管理系统之一,在WEB方面,Mysql是最好的RDBMS(Relat ...

  3. Python学习日记(三) 学习使用dict

    数据按类型可划分为: 不可变数据类型(可哈希):元祖.string.int.bool 可变数据类型(不可哈希):dict.list 集合本身是可变数据类型,元素是不可变数据类型 字典中的key必须是不 ...

  4. Python学习日记(二十一) 异常处理

    程序中异常的类型 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常规错误的基 ...

  5. Python学习日记(三十) Socket模块使用

    Socket(套接字) 套接字是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像文件一样的打开.读写和关闭等操作.套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信.网 ...

  6. Python学习日记(三十二) hmac检验客户端的合法性和socketsever模块

    Hmac模块 其实这个模块类似hashlib模块,它能将一些重要的信息通过算法加密成密文,让信息更具有安全性. 关于hmac加密算法的了解:它的全名是哈希运算消息认证码(Hash-based Mess ...

  7. python学习日记(第一周)

    python学习日记(第一周) 前言: 无论出于什么目的,学个程序语言吧.之前学过一点点基础语法,然后就搁置了两年,日记仅作为个人记录,有问题还望不吝赐教 其实这玩意儿应该每次学一部分记录一部分的,好 ...

  8. Python学习日记-pandas操作学习

    Python学习日记-pandas模块学习 根据需求筛选数据 绘制柱状图-利用pandas绘制 绘制柱状图-利用matplotlib绘制 绘制柱状图-两组数据比较 绘制柱状图-叠加柱状图 绘制饼状图 ...

  9. Python学习日记——罗马数字转整数

    Python学习日记004--罗马数字转整数 题目来源:LeetCode题库--罗马数字转整数 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 ...

最新文章

  1. php checkbox美化,纯CSS3美化radio和checkbox_html/css_WEB-ITnose
  2. 提高ASP性能的最佳选择
  3. php系统毕设答辩问题,计算机专业毕业论文答辩的一般程序及常见问题
  4. AIX修改系统时间 命令
  5. Jquery中使用定时器setInterval和setTimeout
  6. [SOJ] 畅通工程续
  7. 程序员的生存发展和出路
  8. JMeter响应断言详解
  9. Java实现串口通信的小样例
  10. Ubuntu 16.04 + Nginx + Django 项目部署
  11. 《关于Win10系统下Oculus Senser USB无法识别的问题》
  12. java线程等待_java 中线程等待与通知的实现
  13. JAVA-ZIP和GZIP压缩实现
  14. 毕业设计-----------学生选课管理系统的设计
  15. JavaScript计算器
  16. C++面试题(数据结构)
  17. java实现一个语法检查器_Java语法检查
  18. Hadoop性能调优全面总结
  19. mysql攻城掠地_攻城掠地单机武将修改造出自己心目中大神.doc
  20. 结合NAACL2022对计算语言学趋势的思考与分析

热门文章

  1. 520这份花式表白攻略请查收
  2. 征服英语的30个坏习惯
  3. 转载:转载:水平思考:跳出思维定式
  4. 51单片机红外模块学习,必会解读
  5. 社交聆听软件市场现状研究分析-
  6. GridViewAdapter
  7. [创业-24]:职场中,技术人员要避免自己成为一只“仓鼠之轮”上的仓鼠
  8. Android App监听软键盘按键的三种方式 以及 输入法删除退格键的冲突问题解决
  9. 网工如何巧妙找到好工作?
  10. 2022软考网工笔记(Linux篇)