Name | aiokcp JSON |
Version |
0.0.4
JSON |
| download |
home_page | None |
Summary | KCP for asyncio and socketserver, based on kcp |
upload_time | 2024-05-24 06:49:39 |
maintainer | None |
docs_url | None |
author | ryanrain2016 |
requires_python | >=3.8 |
license | None |
keywords |
asyncio
kcp
socket
aio
aiokcp
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# aiokcp
[kcp](https://github.com/skywind3000/kcp)的python实践, 提供了类似python中TCP相关的标准库相同的编程接口(asyncio, socket, socketserver),原tcp代码使用修改导入的方式可以轻松实现从tcp到kcp的平移替换。
## 什么是KCP?
KCP是一个致力于低延时的基于UDP自动重传的可靠传输协议。本身不包含任何网络传输的功能,使用回调的方式处理udp数据包的传输。详情见[kcp](https://github.com/skywind3000/kcp)
## 如何安装
`aiokcp`是基于cython绑定调用的kcp库,打包可能需要安装平台的编译工具。windows系统需要安装`vsbuilder`,linux系统需要安装`gcc`。安装完成后,可以通过`pip`安装
```bash
pip install aiokcp
```
如果需要数据包加密,可以选择安装`cryptography`
```bash
pip install aiokcp[crypto]
```
## 例子
例子详见`aiokcp/examples`目录
### asyncio 低级接口
这里实现了类似`loop.create_connection`和`loop.create_server`的功能
```py
import asyncio
import time
from aiokcp import create_connection, create_server
# copy from document of asyncio.Protocol
class EchoServerProtocol(asyncio.Protocol):
def connection_made(self, transport):
peername = transport.get_extra_info('peername')
print('Connection from {}'.format(peername))
self.transport = transport
def data_received(self, data):
message = data.decode()
print('server: At {} Data received: {!r}'.format(time.time(), message))
print('server: At {} Send: {!r}'.format(time.time(), message))
self.transport.write(data)
print('server: Close the client socket')
self.transport.close()
# copy from document of asyncio.Protocol
class EchoClientProtocol(asyncio.Protocol):
def __init__(self, message, on_con_lost):
self.message = message
self.on_con_lost = on_con_lost
def connection_made(self, transport):
transport.write(self.message.encode())
print('client: At {} Data sent: {!r}'.format(time.time(), self.message))
def data_received(self, data):
print('client: At {} Data received: {!r}'.format(time.time(), data.decode()))
def connection_lost(self, exc):
print('client: The server closed the connection at {}'.format(time.time()))
self.on_con_lost.set_result(True)
async def server():
server = await create_server(EchoServerProtocol, '127.0.0.1', 8888,
kcp_kwargs={ # optional
# ...
})
async with server:
await server.serve_forever()
print('server done')
async def client():
on_con_lost = asyncio.Future()
transport, protocol = await create_connection(
lambda: EchoClientProtocol('Hello World!', on_con_lost),
'127.0.0.1', 8888,
kcp_kwargs={ # optional
# ...
}
)
try:
await on_con_lost
finally:
transport.close()
async def delay_client(delay = 1):
await asyncio.sleep(delay)
await client()
if __name__ == '__main__':
async def main():
await asyncio.gather(server(), client(), delay_client(1))
asyncio.run(main())
```
### asyncio高级接口
```py
import asyncio
import time
from aiokcp import open_connection, start_server
async def handle_echo(reader, writer):
n = 21000
while n:
data = await reader.read(100)
n -= len(data)
message = data.decode()
addr = writer.get_extra_info('peername')
print(f"server: At {time.time()} Received {message!r} from {addr!r}")
print(f"server: At {time.time()} Send: {message!r}")
writer.write(data)
await writer.drain()
print(f"server: At {time.time()} Close the connection")
await asyncio.sleep(10)
writer.close()
await writer.wait_closed()
print(f'server: At {time.time()} Done')
async def kcp_echo_client(message):
reader, writer = await open_connection(
'127.0.0.1', 8888, kcp_kwargs={
# ...
})
print(f'client: At {time.time()} Send: {message!r}', len(message))
writer.write(message.encode())
await writer.drain()
n = len(message)
while n > 0:
data = await reader.read(1000)
print(f'client: At {time.time()} Received: {data.decode()!r}', len(data), n)
n -= len(data)
print(f'client: At {time.time()} Close the connection', '#' * 20)
writer.close()
await writer.wait_closed()
async def server():
server = await start_server(
handle_echo, '127.0.0.1', 8888, kcp_kwargs={
# ...
})
async with server:
await server.serve_forever()
print('server done')
async def main():
await asyncio.gather(server(), kcp_echo_client('Hello World!'))
if __name__ == '__main__':
asyncio.run(main())
```
### 同步的kcp socketpair
```py
from aiokcp.sync import KCPSocket
sock1, sock2 = KCPSocket.socket_pair()
sock1.send(b'123')
print(sock2.recv(100))
sock2.send(b'234')
print(sock1.recv(100))
```
### 同步的kcp 简单服务器-客户端
```py
from aiokcp.sync import KCPSocket
sock1 = KCPSocket.create_server(('127.0.0.1', 18586))
sock2 = KCPSocket.create_connection(('127.0.0.1', 18586))
server_sock, _ = sock1.accept()
server_sock.send(b'123')
print(sock2.recv(100))
sock2.send(b'234')
print(server_sock.recv(100))
```
### 同步的kcp socketserver
```py
import os
import threading
import time
from aiokcp.sync import (BaseRequestHandler, KCPSocket, KCPThreadingServer,
StreamRequestHandler)
class Handler(BaseRequestHandler):
def handle(self):
nbytes = 0
while True:
# self.request is the KCP socket connected to the client
data = self.request.recv(1024)
print("Received from {}:{}".format(*self.client_address))
# print("Data: {}".format(data))
# just send back the same data
# there is no mechanism to check if the connection is broken in kcp, but timeout.
# when timeout occurs, the connection will be closed, recv will return empty bytes
if not data:
break
nbytes += self.request.send(data)
print('server recved: {} sent: {}'.format(nbytes, len(data)))
print('server handle end ##################')
def server_thread(port):
kw = {
'kcp_kwargs': {
# ...
}
}
server = KCPThreadingServer(('127.0.0.1', port), Handler, **kw)
thread = threading.Thread(target=server.serve_forever)
thread.start()
def client_thread(port):
kw = {
'kcp_kwargs': {
# ...
}
}
sock = KCPSocket.create_connection(('127.0.0.1', port), **kw)
sent_buf = b'abc'
sock.send(sent_buf)
for _ in range(1):
b = os.urandom(7 * 1000)
sent_buf += b
sock.send(b)
print('###########', len(sent_buf), '###########')
n = len(sent_buf)
buf = b''
while n > 0:
data = sock.recv(1024)
buf += data
if data:
n -= len(data)
else:
break
print('client recv', len(buf), len(data)) # print(buf, len(data))
if buf[:7003-n] != sent_buf[:7003-n]:
# ensure sent in order
print('error')
print(buf[:7003-n])
print(sent_buf[:7003-n])
break
print('client handle end', '###############')
time.sleep(1)
sock.close()
if __name__ == '__main__':
def thread_test():
from random import randint
port = randint(10000, 20000)
server_thread(port)
client_thread(port)
thread_test()
```
### 同步的kcp socketserver 流处理
```py
import os
import threading
import time
from aiokcp.sync import (BaseRequestHandler, KCPSocket, KCPThreadingServer,
StreamRequestHandler)
class StreamHandler(StreamRequestHandler):
def handle(self):
print('handling')
n = 0
while True:
# self.rfile is a file-like object created by the handler;
# we can now use e.g. readline() instead of raw recv() calls
data = self.rfile.readline().strip()
if not data or data == 'end':
break
n += len(data)
print('server recved: {} sent: {}'.format(n, len(data)))
# Likewise, self.wfile is a file-like object used to write back
# to the client
self.wfile.write(data)
self.wfile.flush()
print('server handle end ##################')
time.sleep(1)
self.wfile.close()
self.request.close()
def server_thread(port):
kw = {
'kcp_kwargs': {
# ...
},
'stream': 1
}
server = KCPThreadingServer(('127.0.0.1', port), StreamHandler, **kw)
thread = threading.Thread(target=server.serve_forever)
thread.start()
def client_thread(port):
kw = {
'kcp_kwargs': {
# ...
},
'stream': 1
}
sock = KCPSocket.create_connection(('127.0.0.1', port), **kw)
sent_buf = b'abc\ndef\nghi\njkl\nmno\npqr\nstu\nvwx\nyza\nend\n'
sock.send(sent_buf)
buf = b''
while len(buf) < 27:
buf += sock.recv(27)
print('client recv', buf)
if __name__ == '__main__':
def thread_test():
from random import randint
port = randint(10000, 20000)
server_thread(port)
client_thread(port)
thread_test()
```
### 可选的udp数据包加密
默认数据包不加密,但提供加密的方法和参数。内置的加密方法需要安装`cryptography`, 采用的aes+cbc模式加密+hmac校验。也可以自定义加密对象, 只需要实现`encrypt`和`decrypt`方法即可
```py
from aiokcp import (create_connection, create_server, open_connection,
start_server)
from aiokcp.crypto import get_crypto
from aiokcp.sync import KCPSocket
# need cryptography installed
key = b'12345678901234567890123456789012'
salt = b'1234567890123456'
crypto = get_crypto(key, salt)
# or
class Crypto:
# need to implement encrypt and decrypt method
def encrypt(self, data):
pass
def decrypt(self, data):
pass
crypto = Crypto()
create_connection(..., crypto=crypto)
create_server(..., crypto=crypto)
open_connection(..., crypto=crypto)
start_server(..., crypto=crypto)
KCPSocket(..., crypto=crypto)
KCPSocket.create_connection(..., crypto=crypto)
KCPSocket.create_server(..., crypto=crypto)
KCPSocket.socket_pair(crypto=crypto)
```
### 相关配置
kcp默认配置如下,可以通过传递`kcp_kwargs`参数到相应的方法,改变相关配置,`kcp_kwargs`不用每个参数都设置,没有设置的使用默认值
```py
default_update_interval = 100 # ms
default_kcp_kwargs = {
'max_transmission': 1400,
'no_delay' : True,
'update_interval' : default_update_interval,
'resend_count' : 2,
'no_congestion_control': False,
'send_window_size': 32,
'receive_window_size': 128,
'stream': 0
}
default_timeout = 600
```
#### 相关配置修改
`KCPServer`, `KCPSteamTransport`, `sync.KCPServer`, `sync.KCPSocket`均提供下面的方法修改相关的配置
```py
def set_nodelay(self, no_delay: bool, update_interval: int, resend_count: int, no_congestion_control: bool):
pass
def set_wndsize(self, send: int, receive: int):
pass
def set_mtu(self, max_transmission: int):
pass
def set_stream(self, stream: bool):
pass
```
# 功能
- [x] asyncio低级接口: Protocol
- [x] asyncio高级接口: Stream
- [x] 同步的kcp socket的实现
- [x] 同步的kcp socketserver的实现
- [x] 可选的udp数据包加密
- [ ] close时通知对方关闭socket
- [ ] 支持tls/ssl
Raw data
{
"_id": null,
"home_page": null,
"name": "aiokcp",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "asyncio, kcp, socket, aio, aiokcp",
"author": "ryanrain2016",
"author_email": "ryanrain2016 <holidaylover2010@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/2c/16/0e0d03a4302569e3c6c917e441a2dcf6c3c155227d6c6fac6b509ea23e1a/aiokcp-0.0.4.tar.gz",
"platform": null,
"description": "# aiokcp\r\n[kcp](https://github.com/skywind3000/kcp)\u7684python\u5b9e\u8df5, \u63d0\u4f9b\u4e86\u7c7b\u4f3cpython\u4e2dTCP\u76f8\u5173\u7684\u6807\u51c6\u5e93\u76f8\u540c\u7684\u7f16\u7a0b\u63a5\u53e3(asyncio, socket, socketserver)\uff0c\u539ftcp\u4ee3\u7801\u4f7f\u7528\u4fee\u6539\u5bfc\u5165\u7684\u65b9\u5f0f\u53ef\u4ee5\u8f7b\u677e\u5b9e\u73b0\u4ecetcp\u5230kcp\u7684\u5e73\u79fb\u66ff\u6362\u3002\r\n\r\n## \u4ec0\u4e48\u662fKCP\uff1f\r\nKCP\u662f\u4e00\u4e2a\u81f4\u529b\u4e8e\u4f4e\u5ef6\u65f6\u7684\u57fa\u4e8eUDP\u81ea\u52a8\u91cd\u4f20\u7684\u53ef\u9760\u4f20\u8f93\u534f\u8bae\u3002\u672c\u8eab\u4e0d\u5305\u542b\u4efb\u4f55\u7f51\u7edc\u4f20\u8f93\u7684\u529f\u80fd\uff0c\u4f7f\u7528\u56de\u8c03\u7684\u65b9\u5f0f\u5904\u7406udp\u6570\u636e\u5305\u7684\u4f20\u8f93\u3002\u8be6\u60c5\u89c1[kcp](https://github.com/skywind3000/kcp)\r\n\r\n## \u5982\u4f55\u5b89\u88c5\r\n`aiokcp`\u662f\u57fa\u4e8ecython\u7ed1\u5b9a\u8c03\u7528\u7684kcp\u5e93\uff0c\u6253\u5305\u53ef\u80fd\u9700\u8981\u5b89\u88c5\u5e73\u53f0\u7684\u7f16\u8bd1\u5de5\u5177\u3002windows\u7cfb\u7edf\u9700\u8981\u5b89\u88c5`vsbuilder`\uff0clinux\u7cfb\u7edf\u9700\u8981\u5b89\u88c5`gcc`\u3002\u5b89\u88c5\u5b8c\u6210\u540e\uff0c\u53ef\u4ee5\u901a\u8fc7`pip`\u5b89\u88c5\r\n```bash\r\npip install aiokcp\r\n```\r\n\u5982\u679c\u9700\u8981\u6570\u636e\u5305\u52a0\u5bc6\uff0c\u53ef\u4ee5\u9009\u62e9\u5b89\u88c5`cryptography`\r\n```bash\r\npip install aiokcp[crypto]\r\n```\r\n\r\n## \u4f8b\u5b50\r\n\u4f8b\u5b50\u8be6\u89c1`aiokcp/examples`\u76ee\u5f55\r\n### asyncio \u4f4e\u7ea7\u63a5\u53e3\r\n\u8fd9\u91cc\u5b9e\u73b0\u4e86\u7c7b\u4f3c`loop.create_connection`\u548c`loop.create_server`\u7684\u529f\u80fd\r\n```py\r\nimport asyncio\r\nimport time\r\n\r\nfrom aiokcp import create_connection, create_server\r\n\r\n\r\n# copy from document of asyncio.Protocol\r\nclass EchoServerProtocol(asyncio.Protocol):\r\n def connection_made(self, transport):\r\n peername = transport.get_extra_info('peername')\r\n print('Connection from {}'.format(peername))\r\n self.transport = transport\r\n\r\n def data_received(self, data):\r\n message = data.decode()\r\n print('server: At {} Data received: {!r}'.format(time.time(), message))\r\n\r\n print('server: At {} Send: {!r}'.format(time.time(), message))\r\n self.transport.write(data)\r\n\r\n print('server: Close the client socket')\r\n self.transport.close()\r\n\r\n# copy from document of asyncio.Protocol\r\nclass EchoClientProtocol(asyncio.Protocol):\r\n def __init__(self, message, on_con_lost):\r\n self.message = message\r\n self.on_con_lost = on_con_lost\r\n\r\n def connection_made(self, transport):\r\n transport.write(self.message.encode())\r\n print('client: At {} Data sent: {!r}'.format(time.time(), self.message))\r\n\r\n def data_received(self, data):\r\n print('client: At {} Data received: {!r}'.format(time.time(), data.decode()))\r\n\r\n def connection_lost(self, exc):\r\n print('client: The server closed the connection at {}'.format(time.time()))\r\n self.on_con_lost.set_result(True)\r\n\r\nasync def server():\r\n server = await create_server(EchoServerProtocol, '127.0.0.1', 8888,\r\n kcp_kwargs={ # optional\r\n # ...\r\n })\r\n async with server:\r\n await server.serve_forever()\r\n print('server done')\r\n\r\nasync def client():\r\n on_con_lost = asyncio.Future()\r\n transport, protocol = await create_connection(\r\n lambda: EchoClientProtocol('Hello World!', on_con_lost),\r\n '127.0.0.1', 8888,\r\n kcp_kwargs={ # optional\r\n # ...\r\n }\r\n )\r\n try:\r\n await on_con_lost\r\n finally:\r\n transport.close()\r\n\r\nasync def delay_client(delay = 1):\r\n await asyncio.sleep(delay)\r\n await client()\r\n\r\nif __name__ == '__main__':\r\n async def main():\r\n await asyncio.gather(server(), client(), delay_client(1))\r\n\r\n asyncio.run(main())\r\n\r\n```\r\n\r\n### asyncio\u9ad8\u7ea7\u63a5\u53e3\r\n```py\r\nimport asyncio\r\nimport time\r\n\r\nfrom aiokcp import open_connection, start_server\r\n\r\n\r\nasync def handle_echo(reader, writer):\r\n n = 21000\r\n while n:\r\n data = await reader.read(100)\r\n n -= len(data)\r\n message = data.decode()\r\n addr = writer.get_extra_info('peername')\r\n\r\n print(f\"server: At {time.time()} Received {message!r} from {addr!r}\")\r\n\r\n print(f\"server: At {time.time()} Send: {message!r}\")\r\n writer.write(data)\r\n await writer.drain()\r\n print(f\"server: At {time.time()} Close the connection\")\r\n await asyncio.sleep(10)\r\n writer.close()\r\n await writer.wait_closed()\r\n print(f'server: At {time.time()} Done')\r\n\r\nasync def kcp_echo_client(message):\r\n reader, writer = await open_connection(\r\n '127.0.0.1', 8888, kcp_kwargs={\r\n # ...\r\n })\r\n\r\n print(f'client: At {time.time()} Send: {message!r}', len(message))\r\n writer.write(message.encode())\r\n await writer.drain()\r\n n = len(message)\r\n while n > 0:\r\n data = await reader.read(1000)\r\n print(f'client: At {time.time()} Received: {data.decode()!r}', len(data), n)\r\n n -= len(data)\r\n\r\n print(f'client: At {time.time()} Close the connection', '#' * 20)\r\n writer.close()\r\n await writer.wait_closed()\r\n\r\nasync def server():\r\n server = await start_server(\r\n handle_echo, '127.0.0.1', 8888, kcp_kwargs={\r\n # ...\r\n })\r\n async with server:\r\n await server.serve_forever()\r\n print('server done')\r\n\r\nasync def main():\r\n await asyncio.gather(server(), kcp_echo_client('Hello World!'))\r\n\r\nif __name__ == '__main__':\r\n asyncio.run(main())\r\n```\r\n\r\n### \u540c\u6b65\u7684kcp socketpair\r\n```py\r\nfrom aiokcp.sync import KCPSocket\r\n\r\nsock1, sock2 = KCPSocket.socket_pair()\r\nsock1.send(b'123')\r\nprint(sock2.recv(100))\r\nsock2.send(b'234')\r\nprint(sock1.recv(100))\r\n```\r\n### \u540c\u6b65\u7684kcp \u7b80\u5355\u670d\u52a1\u5668-\u5ba2\u6237\u7aef\r\n```py\r\nfrom aiokcp.sync import KCPSocket\r\n\r\nsock1 = KCPSocket.create_server(('127.0.0.1', 18586))\r\nsock2 = KCPSocket.create_connection(('127.0.0.1', 18586))\r\nserver_sock, _ = sock1.accept()\r\nserver_sock.send(b'123')\r\nprint(sock2.recv(100))\r\nsock2.send(b'234')\r\nprint(server_sock.recv(100))\r\n```\r\n\r\n### \u540c\u6b65\u7684kcp socketserver\r\n```py\r\nimport os\r\nimport threading\r\nimport time\r\n\r\nfrom aiokcp.sync import (BaseRequestHandler, KCPSocket, KCPThreadingServer,\r\n StreamRequestHandler)\r\n\r\n\r\nclass Handler(BaseRequestHandler):\r\n def handle(self):\r\n nbytes = 0\r\n while True:\r\n # self.request is the KCP socket connected to the client\r\n data = self.request.recv(1024)\r\n print(\"Received from {}:{}\".format(*self.client_address))\r\n # print(\"Data: {}\".format(data))\r\n # just send back the same data\r\n # there is no mechanism to check if the connection is broken in kcp, but timeout.\r\n # when timeout occurs, the connection will be closed, recv will return empty bytes\r\n if not data:\r\n break\r\n nbytes += self.request.send(data)\r\n print('server recved: {} sent: {}'.format(nbytes, len(data)))\r\n print('server handle end ##################')\r\n\r\ndef server_thread(port):\r\n kw = {\r\n 'kcp_kwargs': {\r\n # ...\r\n }\r\n }\r\n server = KCPThreadingServer(('127.0.0.1', port), Handler, **kw)\r\n thread = threading.Thread(target=server.serve_forever)\r\n thread.start()\r\n\r\ndef client_thread(port):\r\n kw = {\r\n 'kcp_kwargs': {\r\n # ...\r\n }\r\n }\r\n sock = KCPSocket.create_connection(('127.0.0.1', port), **kw)\r\n sent_buf = b'abc'\r\n sock.send(sent_buf)\r\n for _ in range(1):\r\n b = os.urandom(7 * 1000)\r\n sent_buf += b\r\n sock.send(b)\r\n print('###########', len(sent_buf), '###########')\r\n n = len(sent_buf)\r\n buf = b''\r\n while n > 0:\r\n data = sock.recv(1024)\r\n buf += data\r\n if data:\r\n n -= len(data)\r\n else:\r\n break\r\n print('client recv', len(buf), len(data)) # print(buf, len(data))\r\n if buf[:7003-n] != sent_buf[:7003-n]:\r\n # ensure sent in order\r\n print('error')\r\n print(buf[:7003-n])\r\n print(sent_buf[:7003-n])\r\n break\r\n print('client handle end', '###############')\r\n\r\n time.sleep(1)\r\n sock.close()\r\n\r\n\r\nif __name__ == '__main__':\r\n def thread_test():\r\n from random import randint\r\n port = randint(10000, 20000)\r\n server_thread(port)\r\n client_thread(port)\r\n\r\n thread_test()\r\n```\r\n### \u540c\u6b65\u7684kcp socketserver \u6d41\u5904\u7406\r\n```py\r\nimport os\r\nimport threading\r\nimport time\r\n\r\nfrom aiokcp.sync import (BaseRequestHandler, KCPSocket, KCPThreadingServer,\r\n StreamRequestHandler)\r\n\r\n\r\nclass StreamHandler(StreamRequestHandler):\r\n def handle(self):\r\n print('handling')\r\n n = 0\r\n while True:\r\n # self.rfile is a file-like object created by the handler;\r\n # we can now use e.g. readline() instead of raw recv() calls\r\n data = self.rfile.readline().strip()\r\n if not data or data == 'end':\r\n break\r\n n += len(data)\r\n print('server recved: {} sent: {}'.format(n, len(data)))\r\n # Likewise, self.wfile is a file-like object used to write back\r\n # to the client\r\n self.wfile.write(data)\r\n self.wfile.flush()\r\n print('server handle end ##################')\r\n time.sleep(1)\r\n self.wfile.close()\r\n self.request.close()\r\n\r\ndef server_thread(port):\r\n kw = {\r\n 'kcp_kwargs': {\r\n # ...\r\n },\r\n 'stream': 1\r\n }\r\n server = KCPThreadingServer(('127.0.0.1', port), StreamHandler, **kw)\r\n thread = threading.Thread(target=server.serve_forever)\r\n thread.start()\r\n\r\ndef client_thread(port):\r\n kw = {\r\n 'kcp_kwargs': {\r\n # ...\r\n },\r\n 'stream': 1\r\n }\r\n sock = KCPSocket.create_connection(('127.0.0.1', port), **kw)\r\n sent_buf = b'abc\\ndef\\nghi\\njkl\\nmno\\npqr\\nstu\\nvwx\\nyza\\nend\\n'\r\n sock.send(sent_buf)\r\n buf = b''\r\n while len(buf) < 27:\r\n buf += sock.recv(27)\r\n print('client recv', buf)\r\n\r\nif __name__ == '__main__':\r\n def thread_test():\r\n from random import randint\r\n port = randint(10000, 20000)\r\n server_thread(port)\r\n client_thread(port)\r\n\r\n thread_test()\r\n```\r\n### \u53ef\u9009\u7684udp\u6570\u636e\u5305\u52a0\u5bc6\r\n\u9ed8\u8ba4\u6570\u636e\u5305\u4e0d\u52a0\u5bc6\uff0c\u4f46\u63d0\u4f9b\u52a0\u5bc6\u7684\u65b9\u6cd5\u548c\u53c2\u6570\u3002\u5185\u7f6e\u7684\u52a0\u5bc6\u65b9\u6cd5\u9700\u8981\u5b89\u88c5`cryptography`, \u91c7\u7528\u7684aes+cbc\u6a21\u5f0f\u52a0\u5bc6+hmac\u6821\u9a8c\u3002\u4e5f\u53ef\u4ee5\u81ea\u5b9a\u4e49\u52a0\u5bc6\u5bf9\u8c61, \u53ea\u9700\u8981\u5b9e\u73b0`encrypt`\u548c`decrypt`\u65b9\u6cd5\u5373\u53ef\r\n```py\r\nfrom aiokcp import (create_connection, create_server, open_connection,\r\n start_server)\r\nfrom aiokcp.crypto import get_crypto\r\nfrom aiokcp.sync import KCPSocket\r\n\r\n# need cryptography installed\r\n\r\nkey = b'12345678901234567890123456789012'\r\nsalt = b'1234567890123456'\r\n\r\ncrypto = get_crypto(key, salt)\r\n\r\n# or\r\n\r\nclass Crypto:\r\n # need to implement encrypt and decrypt method\r\n def encrypt(self, data):\r\n pass\r\n\r\n def decrypt(self, data):\r\n pass\r\n\r\ncrypto = Crypto()\r\n\r\ncreate_connection(..., crypto=crypto)\r\n\r\ncreate_server(..., crypto=crypto)\r\n\r\nopen_connection(..., crypto=crypto)\r\n\r\nstart_server(..., crypto=crypto)\r\n\r\n\r\nKCPSocket(..., crypto=crypto)\r\n\r\nKCPSocket.create_connection(..., crypto=crypto)\r\n\r\nKCPSocket.create_server(..., crypto=crypto)\r\n\r\nKCPSocket.socket_pair(crypto=crypto)\r\n```\r\n\r\n### \u76f8\u5173\u914d\u7f6e\r\nkcp\u9ed8\u8ba4\u914d\u7f6e\u5982\u4e0b\uff0c\u53ef\u4ee5\u901a\u8fc7\u4f20\u9012`kcp_kwargs`\u53c2\u6570\u5230\u76f8\u5e94\u7684\u65b9\u6cd5\uff0c\u6539\u53d8\u76f8\u5173\u914d\u7f6e\uff0c`kcp_kwargs`\u4e0d\u7528\u6bcf\u4e2a\u53c2\u6570\u90fd\u8bbe\u7f6e\uff0c\u6ca1\u6709\u8bbe\u7f6e\u7684\u4f7f\u7528\u9ed8\u8ba4\u503c\r\n```py\r\ndefault_update_interval = 100 # ms\r\n\r\ndefault_kcp_kwargs = {\r\n 'max_transmission': 1400,\r\n 'no_delay' : True,\r\n 'update_interval' : default_update_interval,\r\n 'resend_count' : 2,\r\n 'no_congestion_control': False,\r\n 'send_window_size': 32,\r\n 'receive_window_size': 128,\r\n 'stream': 0\r\n}\r\n\r\ndefault_timeout = 600\r\n```\r\n#### \u76f8\u5173\u914d\u7f6e\u4fee\u6539\r\n`KCPServer`, `KCPSteamTransport`, `sync.KCPServer`, `sync.KCPSocket`\u5747\u63d0\u4f9b\u4e0b\u9762\u7684\u65b9\u6cd5\u4fee\u6539\u76f8\u5173\u7684\u914d\u7f6e\r\n```py\r\ndef set_nodelay(self, no_delay: bool, update_interval: int, resend_count: int, no_congestion_control: bool):\r\n pass\r\n\r\ndef set_wndsize(self, send: int, receive: int):\r\n pass\r\n\r\ndef set_mtu(self, max_transmission: int):\r\n pass\r\n\r\ndef set_stream(self, stream: bool):\r\n pass\r\n```\r\n\r\n# \u529f\u80fd\r\n- [x] asyncio\u4f4e\u7ea7\u63a5\u53e3: Protocol\r\n- [x] asyncio\u9ad8\u7ea7\u63a5\u53e3: Stream\r\n- [x] \u540c\u6b65\u7684kcp socket\u7684\u5b9e\u73b0\r\n- [x] \u540c\u6b65\u7684kcp socketserver\u7684\u5b9e\u73b0\r\n- [x] \u53ef\u9009\u7684udp\u6570\u636e\u5305\u52a0\u5bc6\r\n- [ ] close\u65f6\u901a\u77e5\u5bf9\u65b9\u5173\u95edsocket\r\n- [ ] \u652f\u6301tls/ssl\r\n",
"bugtrack_url": null,
"license": null,
"summary": "KCP for asyncio and socketserver, based on kcp",
"version": "0.0.4",
"project_urls": {
"Homepage": "https://github.com/ryanrain2016/aiokcp",
"Issues": "https://github.com/ryanrain2016/aiokcp/issues"
},
"split_keywords": [
"asyncio",
" kcp",
" socket",
" aio",
" aiokcp"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "e691ea8aec253eaf86fdd92086d83de12fba31a1399cbc5ae8f952ed0a38d7a0",
"md5": "41032ea6ec86dc622d96d87a629fb580",
"sha256": "4b3fa0aa67c7589637bd8432165cee087e9e3478af1bf7ee2fd64832d47778ce"
},
"downloads": -1,
"filename": "aiokcp-0.0.4-cp310-cp310-win_amd64.whl",
"has_sig": false,
"md5_digest": "41032ea6ec86dc622d96d87a629fb580",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.8",
"size": 176629,
"upload_time": "2024-05-24T06:49:37",
"upload_time_iso_8601": "2024-05-24T06:49:37.873758Z",
"url": "https://files.pythonhosted.org/packages/e6/91/ea8aec253eaf86fdd92086d83de12fba31a1399cbc5ae8f952ed0a38d7a0/aiokcp-0.0.4-cp310-cp310-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2c160e0d03a4302569e3c6c917e441a2dcf6c3c155227d6c6fac6b509ea23e1a",
"md5": "3e1c4a6c8cbc87963a179429636e6311",
"sha256": "e1f8455d8e87bd711e993cead22191896336f8be1bd37212f515a26146bf152e"
},
"downloads": -1,
"filename": "aiokcp-0.0.4.tar.gz",
"has_sig": false,
"md5_digest": "3e1c4a6c8cbc87963a179429636e6311",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 123239,
"upload_time": "2024-05-24T06:49:39",
"upload_time_iso_8601": "2024-05-24T06:49:39.736980Z",
"url": "https://files.pythonhosted.org/packages/2c/16/0e0d03a4302569e3c6c917e441a2dcf6c3c155227d6c6fac6b509ea23e1a/aiokcp-0.0.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-24 06:49:39",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ryanrain2016",
"github_project": "aiokcp",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "aiokcp"
}