线程套接字无法使用sendall

时间:2019-11-12 22:44:42

标签: python multithreading sockets tcp

我当前遇到一个问题,即以下代码仅从套接字读取前1028个字节,然后挂起等待更多,即使其余的已发送。我以为可能是导致问题的代码,但是仅当我从客户端到服务器(多线程)接收数据时才会发生。当我反向运行代码(服务器向客户端发送数据)时,它没有问题。

这是当前失败的原因:

客户代码:

with open(commands[1], "rb") as file:
     data = file.read()

     # Sends the length of the file to the server
     serverSocket.sendall(str(len(data)).encode())


     # Sends the data to the server
     data = file.read(1024)
     while data:
          data = file.read(1024)
          serverSocket.sendall(data)

有关服务器代码:

        # Gets the total length of the file
        dataLen = int(clientsocket.recv(1024).decode())
        totalData = ""

        while len(totalData) < dataLen:
            # Reads in and appends the data to the variable
            data = clientsocket.recv(1024).decode()
            totalData += data

我还尝试了什么? 客户的原始代码为:

with open(commands[1], "rb") as file:
     data = file.read()

     # Sends the length of the file to the server
     serverSocket.sendall(str(len(data)).encode())


     # Sends the data to the server
     serverSocket.sendall(data)

我之所以改变,是因为我认为recv可能无法从客户端获取所有数据包,但是客户端认为一切都已发送。

最低可复制代码

SERVER.PY

from socket import socket, AF_INET, SOCK_STREAM, error
from threading import Thread, Lock
from _thread import interrupt_main

import logging
from sys import stdout

from os import makedirs
from pathlib import Path

class Server:

def __init__(self, host, port):

    logging.basicConfig(stream=stdout, level=logging.INFO, format='%(asctime)s - %(message)s')

    self.host = host
    self.port = port
    self.quitVal = False
    self.threads = []
    self.lock = Lock()
    self.sock = None
    self.open()

def open(self):
    sock = socket(AF_INET, SOCK_STREAM)
    sock.bind((self.host, self.port))
    sock.listen(5)
    self.sock = sock

def listen(self):

    try:
        while self.quitVal != True:
            (clientsocket, address) = self.sock.accept()
            # This creates a threaded connection as this is the choke for the connection
            thread = Thread(target=self.connection, args=(clientsocket, address), daemon=True)
            self.threads.append(thread)
            thread.start()
    except OSError:
        quit()

def connection(self, clientsocket, address):
    while self.quitVal != True:
        # We are going to allow multiple file transfers at one time on a connection
        requestThreads = []          

        # The client innitially sends a command "s<command> [<fileLocation>]"
        data = clientsocket.recv(4096).decode("utf-8")

        data = data.split()
        data[0] = data[0].lower()

        if data[0] == "get":
            thread = Thread(target=self.get, args=(clientsocket, data[1]), daemon=True)
            requestThreads.append(thread)
            thread.start()

        elif data[0] == "put":
            thread = Thread(target=self.put, args=(clientsocket, data[1]), daemon=True)
            requestThreads.append(thread)
            thread.start()
    clientsocket.close()

def get(self, clientsocket, fileLocation):

    # Tries to get the file, and sends it all to the client
    with self.lock:
        try:
            with open(fileLocation, "rb") as file:
                data = file.read()

                # Sends the length of the file to the client
                clientsocket.sendall(str(len(data)).encode())

                # Byte to separate the input from length and file
                response = self.sock.recv(1).decode()

                # Sends the data to the client
                clientsocket.sendall(data)

        except IOError as e:
            print("\nFile doesn't exist")


def put(self, clientsocket, fileLocation):
    # Gets the total length of the file
    with self.lock:
        dataLen = int(clientsocket.recv(1024).decode())
        totalData = ""

        # Gets the total length of the file
        dataLen = int(clientsocket.recv(1024).decode())
        totalData = ""

        # Byte to separate the input from length and file
        clientsocket.sendall("0".encode())

        while len(totalData) < dataLen:
            # Reads in and appends the data to the variable
            data = clientsocket.recv(2048).decode()
            totalData += data

        logging.info(totalData)

server = Server("127.0.0.1", 10002)
server.listen()

CLIENT.PY

from socket import socket, AF_INET, SOCK_STREAM, error
from threading import Thread, Lock
from _thread import interrupt_main

import logging
from sys import stdout

from os import makedirs
from pathlib import Path


class Client:

def __init__(self, host, port):

    self.host = host
    self.port = port
    self.quitVal = False
    self.sock = self.open()
    self.threads = []
    self.lock = Lock()   

def open(self):
    try:
        sock = socket(AF_INET, SOCK_STREAM)
        sock.connect((self.host, self.port))
    except error as err:
        return None
    return sock

def get(self, commands):
    # Sends the request for the file to the server using the main Sock        
    with self.lock:
        command = "GET " + commands[0]
        self.sock.send(command.encode()) 

        dataLen = int(self.sock.recv(1024).decode())
        totalData = ""

        self.sock.sendall("0".encode())


        while len(totalData) < dataLen:
            data = self.sock.recv(2048).decode()
            totalData += data


def put(self, commands):

    with self.lock:
        # Sends the put call command to the server
        command = "PUT " + commands[1]
        self.sock.sendall(command.encode())

        try:
            with open(commands[1], "rb") as file:
                data = file.read()

                # Sends the length of the file to the server
                self.sock.sendall(str(len(data)).encode())

                # Byte to separate the input from length and file
                response = self.sock.recv(1).decode()

                # Sends the data to the server
                self.sock.sendall(data)    
        except IOError as e:
            logging.info("\nFile doesn't exist")

client = Client("127.0.0.1", 10002)
print("foo")
client.get(["foo.txt", "bar.txt"])
client.put(["foo.txt", "bar1.txt"])

0 个答案:

没有答案