发送文件后我无法从我的服务器获取数据

I can not get the data from my server after having sent a file thought sockets

我在收到数据后尝试发送确认时遇到问题。
要恢复这种情况,我有一个客户端有一个文件要发送到正在侦听的服务器。当服务器收到此文件时,它 returns 一个确认文件。这是我的问题。当我的服务器发送 ACK 文件时,我的客户端没有收到它,只是站在这里不做任何其他事情。

server.py

import socket
import signal
import os

# "all" interfaces
SERVER_HOST = "0.0.0.0"
SERVER_PORT = 8000

BUFFER_SIZE = 4096
SEPARATOR = "<SEPARATOR>"


# Setting Dicionnaries for HL7 ACK Requirements
MSH = {3:'HOSPITAL', 4:'RESULTS', 5:'LAB400', 6:'RESULTS',7:'20201030084524',9:'ACK', 10:'1452357', 11:'P',12:'2.2', 15:'AL', 16:'NE', 17:'CHE'}
MSA = {1:'AA', 2:'1722178'}

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# test the binding
try:
    socket.bind((SERVER_HOST, SERVER_PORT))

except socket.error as error:

    print('Bind failed. Error Code : '
          + str(error[0]) + ' Message ' 
          + error[1])

    exit()

def signal_handler(sign, frame):

    print('[*] Shutting down')
    exit(0)

while signal.signal(signal.SIGINT, signal_handler):

    # connection limit(5 connection try then deny)
    socket.listen(5)

    print(f"[*] Listening as {SERVER_HOST}:{SERVER_PORT}")

    # accept the connection if there is any
    client_socket, address = socket.accept() 

    # Below code is executed if sender is connected
    print(f"[+] {address} is connected.")

    # get what the client is sending
    received = client_socket.recv(BUFFER_SIZE).decode()

    filename, fileSize = received.split(SEPARATOR)

    #convert to integer
    fileSize = int(fileSize)

    # remove absolute path if there is
    filename = os.path.basename(filename)

    # start receiving the file from the socket and writing to the file stream
    with open(f".\Files\{filename}", "wb") as f:

        while True:

            # read 1024 bytes from the socket (receive)
            bytes_read = client_socket.recv(BUFFER_SIZE)     

            if not bytes_read:    

                # file transmitting is done
                print(f"[+] File transfert is done")
                print(f"[+] File saved")
                break

            # write to the file the bytes we just received
            f.write(bytes_read)
    
    
    myfile = open(".\Files\ack.hl7", "rb")
    client_socket.send(myfile.read())
    
    client_socket.close()

    socket.close

client.py

import socket
import os
import random

SEPARATOR = "<SEPARATOR>"
BUFFER_SIZE = 4096

HOST = "127.0.0.1"
PORT = 8000

files = ["test1.HL7","test2.HL7","test3.HL7","test4.HL7","test5.HL7","test6.HL7","test7.HL7","test8.HL7"]

# fileName = f".\ClientFiles\{files[random.randrange(1,8)]}"

fileName = f".\ClientFiles\{files[0]}"

filesize = os.path.getsize(fileName)

socket = socket.socket()

print(f"[+] Connecting to {HOST}:{PORT}")

socket.connect((HOST, PORT))

print("[+] Connected.")

socket.send(f"{fileName}{SEPARATOR}{filesize}".encode())

# opening file
with open(fileName, "rb") as f:
    while True:
        # reading bytes
        bytes_read = f.read(BUFFER_SIZE)
        if not bytes_read:
            # Transmitting is done
            break
        # send all the buffer
        socket.sendall(bytes_read)
print(f"[+] File {fileName} sent")



data = socket.recv(BUFFER_SIZE)

print(data)

print("[*] Closing")
socket.close()

我不明白为什么它不起作用

这是我需要传输的文件(顺便说一句,是一些 HL7 V2.5.1)

Ack.hl7

MSH|^~\&|HOSPITAL|RESULTS|LAB400|RESULTS|20201030084524||ACK|1452357|P|2.2
MSA|AA|1722178

testFile.hl7

MSH|^~\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A04|MSG00001|P|2.4
EVN|A01-|198808181123
PID|||PATID1234^5^M11||JONES^WILLIAM^A^III||19610615|M-||2106-3|1200 N ELM STREET^^GREENSBORO^NC^27401-1020|GL|(919)379-1212|(919)271-3434~(919)277-3114||S||PATID12345001^2^M10|123456789|9-87654^NC
NK1|1|JONES^BARBARA^K|SPO|||||20011105
NK1|1|JONES^MICHAEL^A|FTH
PV1|1|I|2000^2012^01||||004777^LEBAUER^SIDNEY^J.|||SUR||-||1|A0-
AL1|1||^PENICILLIN||PRODUCES HIVES~RASH
AL1|2||^CAT DANDER
DG1|001|I9|1550|MAL NEO LIVER, PRIMARY|19880501103005|F||
PR1|2234|M11|111^CODE151|COMMON PROCEDURES|198809081123
ROL|45^RECORDER^ROLE MASTER LIST|AD|CP|KATE^SMITH^ELLEN|199505011201
GT1|1122|1519|BILL^GATES^A
IN1|001|A357|1234|BCMD|||||132987
IN2|ID1551001|SSN12345678
ROL|45^RECORDER^ROLE MASTER LIST|AD|CP|KATE^ELLEN|199505011201

到目前为止我尝试了什么

On my client

我尝试重新创建套接字以防它无法响应

try:
    data = socket.recv(BUFFER_SIZE)
    print(data)
except:
    # recreate the socket and reconnect
    socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket.connect(HOST, PORT)
    data = socket.recv(BUFFER_SIZE)
    print(data)

我可以重现并理解你的问题。

根本原因是TCP是流协议。这意味着唯一的保证是从一侧发送的所有字节都将以相同的顺序被对等方接收。但是数据包可能会被网络上的任何元素连接或拆分,包括任何一方的协议栈。

所以在server.py中,这是错误的:

# get what the client is sending
received = client_socket.recv(BUFFER_SIZE).decode()

filename, fileSize = received.split(SEPARATOR)

#convert to integer
fileSize = int(fileSize)

因为收到的可以包含数据的开头...

稳健的方法是:

# get what the client is sending
received = client_socket.recv(BUFFER_SIZE)

filename, bytes_read = received.split(SEPARATOR.encode())
fileSize = bytes(itertools.takewhile(
    lambda i: bytes((i,)).isdigit(), bytes_read))
bytes_read = bytes_read[len(fileSize):]
#convert to integer
fileSize = int(fileSize)
filename = filename.decode()

并且您将在 bytes_read 中拥有数据的开头(以字节为单位)并且应该立即写入:

# start receiving the file from the socket and writing to the file stream
with open(f".\Files\{filename}", "wb") as f:
    f.write(bytes_read)

    while True:
        ...

但这还不是全部。仍在 server.py 中,读取循环不会 return 空缓冲区,直到对等方关闭或更好地关闭套接字。

所以在client.py你必须发出传输结束信号:

print(f"[+] File {fileName} sent")

socket.shutdown(SHUT_WR)   # tells peer that nothing will be sent any more

data = socket.recv(BUFFER_SIZE)