在windows系统中对套接字数据进行io时为啥不可以直接使用文件io相关函数?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在windows系统中对套接字数据进行io时为啥不可以直接使用文件io相关函数?相关的知识,希望对你有一定的参考价值。

参考技术A 到目前为止的所有例子中,我们一直使用也称为Unix I/O——包括read、write这两个函数及它们的变体(recv、send等等)——的函数执行I/O。这些函数围绕描述符(descriptor)工 作,通常作为Unix内核中的系统调用实现
执行I/O的另一个方法是使用标准I/O函数库(standard I/O library)。这个函数库由ANSI C标 准规范,意在便于移植到支持ANSI C的非Unix系统上。标准I/O函数库处理我们直接使用Unix I/O 函数时必须考虑的一些细节,譬如自动缓冲输入流和输出流。不幸的是,它对于流的缓冲处理可能导致我们同样必须考虑的一组新的问题。APUE第5章详细讨论了标准I/O函数库,[Plauger 1992]给出并讨论了标准I/O函数库的一个完整的实现。

为啥在 python 中对 asyncio 服务器的多个请求的时间会增加?

【中文标题】为啥在 python 中对 asyncio 服务器的多个请求的时间会增加?【英文标题】:why is time rising for more than one request to asyncio server in python?为什么在 python 中对 asyncio 服务器的多个请求的时间会增加? 【发布时间】:2018-07-04 12:51:19 【问题描述】:

我用套接字编写了一个 pythonic 服务器。它应该同时(并行)接收请求并并行响应它们。 当我向它发送多个请求时,回复的时间比我预期的要长。

服务器:

import datetime
import asyncio, timeit
import json, traceback
from asyncio import get_event_loop

requestslist = []
loop = asyncio.get_event_loop()

async def handleData(reader, writer):
    message = ''
    clientip = ''
    data = bytearray()
    print("Async HandleData", datetime.datetime.utcnow())


    try:
        start = timeit.default_timer()
        data = await reader.readuntil(separator=b'\r\n\r\n')
        msg = data.decode(encoding='utf-8')
        len_csharp_message = int(msg[msg.find('content-length:') + 15:msg.find(';dmnid'):])
        data = await reader.read(len_csharp_message)
        message = data.decode(encoding='utf-8')

        clientip = reader._transport._extra['peername'][0]
        clientport = reader._transport._extra['peername'][1]
        print('\nData Received from:', clientip, ':', clientport)
        if (clientip, message) in requestslist:
            reader._transport._sock.close()

        else:
            requestslist.append((clientip, message))

            # adapter_result = parallel_members(message_dict, service, dmnid)
            adapter_result = '''["name": "data": "data", "type": "str"]'''
            body = json.dumps(adapter_result, ensure_ascii=False)
            print(body)

            contentlen = len(bytes(str(body), 'utf-8'))
            header = bytes('Content-Length:'.format(contentlen), 'utf-8')
            result = header + bytes('\r\n\r\n', 'utf-8') + body + bytes('', 'utf-8')
            stop = timeit.default_timer()
            print('total_time:', stop - start)
            writer.write(result)
            writer.close()
        writer.close()
        # del writer
    except Exception as ex:
        writer.close()
        print(traceback.format_exc())
    finally:
        try:
            requestslist.remove((clientip, message))
        except:
            pass


def main(*args):
    print("ready")
    loop = get_event_loop()
    coro = asyncio.start_server(handleData, 'localhost', 4040, loop=loop, limit=204800000)
    srv = loop.run_until_complete(coro)
    loop.run_forever()


if __name__ == '__main__':
    main()

当我发送单个请求时,需要 0.016 秒。 但是对于更多的请求,这次增加。

cpu 信息:intel xeon x5650

客户:

import multiprocessing, subprocess
import time
from joblib import Parallel, delayed


def worker(file):
    subprocess.Popen(file, shell=False)


def call_parallel (index):
    print('begin ' , index)
    p = multiprocessing.Process(target=worker(index))
    p.start()
    print('end ' , index)

path = r'python "/test-Client.py"'     # ## client address
files = [path, path, path, path, path, path, path, path, path, path, path, path]
Parallel(n_jobs=-1, backend="threading")(delayed(call_parallel)(i) for index,i  in  enumerate(files))

对于这个同步发送 12 个请求的客户端,每个请求的总时间为 0.15 秒。

我希望任何数量的请求,时间都是固定的。

【问题讨论】:

【参考方案1】:

什么是请求

单个请求(粗略地说)包括以下步骤:

    将数据写入网络 浪费时间等待答复 从网络读取答案

№1/№3 由您的 CPU 处理得非常快。第 2 步 - 从您的 PC 到某个服务器(例如在另一个城市)并通过电线返回的字节旅程:通常需要更多时间。

异步请求的工作原理

就处理而言,异步请求并不是真正的“并行”:它仍然是您的单个 CPU 内核,一次可以处理一件事。但是运行多个异步请求允许您使用某个请求的第 2 步来执行其他请求的第 1 步/第 3 步,而不仅仅是浪费大量时间。这就是为什么多个异步请求通常会比相同数量的同步请求更早完成的原因。

在没有网络延迟的情况下运行异步代码

但是当您在本地运行时,第 2 步不会花费太多时间:您的 PC 和服务器是同一个东西,字节不会进入网络旅程。在第 2 步中没有时间可以用来启动新请求。一次只有一个 CPU 内核可以处理一件事。

您应该针对响应延迟的服务器测试请求,以查看您期望的结果。

【讨论】:

我在服务器写入结果之前将 3 秒设置为延迟。每个请求收到响应 3 秒 + 之前的请求时间。例如:第一次请求时间:0.0012 秒。第二次请求时间:3.010 秒。第三次请求时间:6.027 秒。 ... 第 9 次请求时间:24.11 秒。

以上是关于在windows系统中对套接字数据进行io时为啥不可以直接使用文件io相关函数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 python 中对 asyncio 服务器的多个请求的时间会增加?

为啥在这种情况下套接字 io 不接收消息?

为啥在 AWS Redshift 中对密码进行 md5 哈希处理时密码身份验证失败?

windows下的IO模型之选择(select)模型

为啥 sortBy() 不能在 Spark 中对数据进行均匀排序?

Windows 中对套接字的 closesocket() 调用需要 20 秒 [关闭]