【问题标题】:python socket - how to complete/close the connection on the client side?python socket - 如何在客户端完成/关闭连接?
【发布时间】:2021-11-28 17:21:04
【问题描述】:

server.py:

这里使用来自 NVD 的 json 文件

import socket, json, random, threading, zipfile, requests, re, zipfile
from bs4 import BeautifulSoup
from zipfile import *
      

def listen_user(user):
    for x in range(2018,2021,1):
        filename = "nvdcve-1.1-" + str(x) + ".json"
        print(filename)
        with open(filename, 'rb') as file:
            sendfile = file.read()
        user.sendall(sendfile)
        print('file sent' + str(x))

def start_server():
    while True:
        user_socket, address = server.accept()
        print(f"User <{address[0]}> connected!")

        users.append(user_socket)
        listen_accepted_user = threading.Thread(
            target=listen_user,
            args=(user_socket,)
        )

        listen_accepted_user.start()

if __name__ == '__main__':
    users = []
    server = socket.socket(
        socket.AF_INET,
        socket.SOCK_STREAM,
    )

    server.bind(
        ("127.0.0.1", 100)
    )

    server.listen(5)
    print('waiting for connection...')
    start_server()

client.py

import socket, json, random
from threading import Thread

def start_client(client):
    savefilename = str(random.randint(1,10)) + 'new.json'
    print(savefilename)
    with client,open(savefilename,'wb') as file:
        while True:
            recvfile = client.recv(4096)
            if not recvfile:
                print('1 client')
                break
            file.write(recvfile)
    file.close()
    print('2 client')
    client.close()


if __name__ == '__main__':
    client = socket.socket(
        socket.AF_INET,
        socket.SOCK_STREAM,
    )
    client.connect(
        ("127.0.0.1", 100)
    )
    start_client(client)

当我发送文件时 - 它们几乎全部发送,但程序未到达“打印('1 客户端')”或“打印('2 客户端')”行

并且 *new 文件包含除了最后几行之外的所有行

请帮忙 - 如何修复代码?

【问题讨论】:

  • 能否提供pip freeze 命令的输出?由于模型导入错误,我无法启动服务器模块。

标签: python json python-3.x sockets server


【解决方案1】:

调用client.recv(4096) 表示您正在等待接收 4096 个字节,然后对这些字节进行处理。在这种情况下可能发生的情况是您正在写出所有字节,减去最后没有完全填满缓冲区的字节。这会让客户端等待一个缓冲区,该缓冲区的空间尚未准备好写出。

我猜你假设client.recv() 将在你获得所有数据后返回一个空字符串;根据您的代码,情况并非如此。如果您希望客户端能够终止连接,您将需要发送某种控制序列或尝试以其他方式评估从服务器接收到的字节以确定何时关闭连接。如果这样做,您可能希望在调用 client.recv() 时将 bufsize 设置为 1,而是在写入文件之前使用其他方法进行缓冲。

例如,由于您要发送 JSON 数据,您可以将字节连接到一个变量,然后反复尝试解析 JSON。成功解析 JSON 后,您可以在客户端终止连接(尽管这意味着您必须为要发送的每个文件打开一个新连接)。

但是,这提出了一个问题:为什么需要从客户端关闭?通常,一旦发送完所有相关数据,服务器就会关闭连接。

【讨论】:

    【解决方案2】:

    recvfile = client.recv(4096) 在 while 循环内,它一直在等待接收下一个字节。客户端不知道文件已发送,因此它等待下一个 4096 字节并且不退出循环。

    为了让客户端知道文件传输已完成,您可以从 server.py 发送一条消息,您可以在客户端中验证并打破循环,如下所示。

    server.py

    def listen_user(user):
        for x in ["f.json","g.json"]:
            filename = x
            print(filename)
            with open(filename, 'rb') as file:
                sendfile = file.read()
            user.sendall(sendfile)
            print('file sent' + str(x))
        user.send(b"Done")
    

    Client.py

    def start_client(client):
        savefilename = str(random.randint(1,10)) + 'new.json'
        print(savefilename)
        with client,open(savefilename,'wb') as file:
            while True:
                recvfile = client.recv(4096)
                if recvfile.decode("utf-8") =="Done":
                    print('1 client')
                    file.close()
                    break
                file.write(recvfile)
        print('2 client')
        client.close()
    

    【讨论】:

    • 如果 recvfile.decode("utf-8") 中的 "DoneDoneDone": print('1 client') file.write(recvfile) break file.write(recvfile)
    • 感谢您的回答,我做到了,程序开始工作了
    猜你喜欢
    • 2021-03-25
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2013-08-13
    相关资源
    最近更新 更多