通过套接字收到 ACK 后,我无法从我的客户端发送 ack 确认

I cannot send an ack confirmation from my client after receiving an ACK through socket

我有一台服务器一直在监听并等待连接。当一个客户端连接然后向它发送一个文件时,它接收它,保存它然后发回一个 ACK​​ 文件,我的客户端发回确认他收到了 ACK,最后我的服务器关闭了连接,我的客户端也关闭了。

我在尝试从我的客户端接收 ACK 时出现 ,但现在已解决。

但是,现在我关闭了与 SHUT_WR 的套接字连接(如果我是对的,这表明我们将在此之后停止发送)我无法重新发送我的确认。

我不知道这是怎么回事,我怎么能:

来自我的客户

  1. 发送一个文件到我的服务器
  2. 从我的服务器收到 ACK
  3. 重新发送确认

来自我的服务器

  1. 接收文件
  2. 发送 ACK
  3. 收到确认

我卡住了。除非我尝试接收或发送某些内容,否则我的服务器正在运行。

以下代码块是我的实际文件

client.py


import socket
import os
import random
from socket import SHUT_WR

SEPARATOR = "<SEPARATOR>"
BUFFER_SIZE = 8192

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)]}"

filesize = os.path.getsize(fileName)

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

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:
    print("[*] Reading")
    while True:
        # reading bytes
        bytes_read = f.read(BUFFER_SIZE)
        if not bytes_read:
            # Transmitting is done
            print("[+] File reading is done.")
            break
        # send all the buffer
        socket.sendall(bytes_read)
print(f"[+] File {fileName} sent")

socket.shutdown(SHUT_WR)

print("[*] Waiting for an acknowledgment")

data = socket.recv(BUFFER_SIZE)

print("[+] Acknoledgment recieved")

print(data.decode())

socket.sendall(data.decode().split('|')[9].encode())

print("[+] Acknowledgment confirmation sent")

print("[*] Closing")

socket.close()

server.py

import itertools

import socket

import signal

import ntpath

from pathlib import Path

from consts import *
from helper import *

# Setting Dicionnaries for HL7 ACK Requirements
MSH = {0:'MSH',2:'', 3:'', 4:'', 5:'', 6:'', 7:'', 8:'', 9:'', 10:'', 11:'',12:'', 13:'', 14:'', 15:'NE', 16:'AL', 17:'', 18:'', 19:'', 20:'', 21:''}
MSA = {0:'MSA', 1:'AA', 2:''}
ACK = {'MSH':{}, 'MSA':{}}

def hl7_ack_generator():
    """Generate the Acknowledgement file and sends it to the client

    Returns:
        String: Returns the Acknowledgment filename
    """
    content = ""

    # Switch sender-receiver
    MSH[3], MSH[5], MSH[4], MSH[6] = MSH[5], MSH[3], MSH[6], MSH[4]

    # Set the message type.
    # If possible get the message trigger to return the same trigger
    try:
        MSH[9] = f"ACK^{check_msh_9_trigger_event(MSH[9].decode().split('^'))}^ACK"
    except:
        MSH[9] = "ACK"

    # Set MSH values
    for param in MSH:
        ACK['MSH'][param] = MSH.get(param)
    # Set MSA values
    for param in MSA:
        ACK['MSA'][param] = MSA.get(param)
    # Create the ACK message
    # Handle integers & bytes in each fields
    # Get MSH values
    for i in range(0,21) :
        if i != 1:
            if ACK['MSH'][i]:
                # Generate a message id based on recieved message timestamp and message id 
                # not exceeding 20 chars
                if i == 10:
                    ACK['MSH'][10] = ACK['MSH'][7].decode() + ACK['MSH'][10].decode()
                    if len(ACK['MSH'][10]) > 20:
                        ACK['MSH'][10] = ACK['MSH'][10][:20]
                    content += ACK['MSH'][10]
                else:
                    try:
                        content += ACK['MSH'][i].decode()
                    except:
                        if not ACK['MSH'][i] == None:
                            content += ACK['MSH'][i]
            content += '|'
    content += "\r"
    # Get MSA values
    for i in range(0,3):
        try:
            content += ACK['MSA'][i].decode()
        except:
            if not ACK['MSA'][i] == None:
                content += ACK['MSA'][i]
        content += "|"

    # Create the ACK filename
    filename = ACK['MSH'][10] + "_ACK.HL7"

    # create the ACK file and write its content
    with open(Path(SERVER_ACK_FILES_FOLDER + filename), "w") as f:
        f.write(content)
        f.close()

    return filename

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()

# Handle ctrl+c
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)

    filename, bytes_read = received.split(SEPARATOR.encode())

    # get the file size
    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()

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

    # start receiving the file from the socket and writing to the file stream
    with open(Path(SERVER_FILES_FOLDER + filename), "wb") as f:

        print("[+] File received")

        while True:
            # write to the file the bytes we just received
            f.write(bytes_read)

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

            if bytes_read.startswith(b'MSH'):
                messageHeader = bytes_read.partition(b'\r')[0].split(b'|')
                j = 0
                i = 2
                for i in range(2,17):
                    j+=1
                    # Exclude MSH fields(constant and/or unwanted)
                    if i not in (15,16):
                        MSH[i]= messageHeader[j]
                    #Get message ID
                    if i == 10:
                        MSA[2] = messageHeader[j]
                ackFilename = hl7_ack_generator()

            if not bytes_read:
                # file transmitting is done
                print("[+] File transfert is done")
                break

    with open(Path(SERVER_ACK_FILES_FOLDER + ackFilename), "rb") as f:
        while True:
            bytes_read = f.read(BUFFER_SIZE)
            if not bytes_read:
                print("[+] Acknoledgment Sent")
                break
            client_socket.sendall(bytes_read)

    confirmation = client_socket.recv(BUFFER_SIZE)

    print(confirmation)

    print("[+] Confirmation received")

    print("[*] Closing conneciton")

    client_socket.close()

    socket.close

testX.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

感谢关注!

我把我的服务器改成这样:

final_size = b''

while True:
    # write to the file the bytes we just received
    f.write(bytes_read)

    final_size += bytes_read
            
    if len(final_size) >= fileSize:
        # file transmitting is done
        print("[+] File transfert is done")
        break

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

        if bytes_read.startswith(b'MSH'):
            messageHeader = bytes_read.partition(b'\r')[0].split(b'|')
            j = 0
            i = 2
            for i in range(2,17):
                j += 1
                # Exclude MSH fields(constant and/or unwanted)
                if i not in (15,16):
                    MSH[i]= messageHeader[j]
                    #Get message ID
                    if i == 10:
                        MSA[2] = messageHeader[j]
                ackFilename = hl7_ack_generator()

还有我的客户:

print(f"[+] File {fileName} sent")
print("[*] Waiting for an acknowledgment")

data = sock.recv(BUFFER_SIZE)

print("[+] Acknoledgment recieved")

sock.sendall(data.decode().split('|')[9].encode())

print("[+] Acknowledgment confirmation sent")

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