从客户端接收回数据

2022-03-11 00:00:00 python numpy sockets client-server

问题描述

我使用套接字连接将一个缩放数组从服务器发送到客户端,现在它工作得很好,我想将数据发回服务器,以便在服务器中取消它的缩放。数据一次每行发送到客户端,因此我尝试将它们放回一个名为Final的空数组中。

这是server.py

import socket
import numpy as np
import pandas as pd
import sklearn
from sklearn.preprocessing import MinMaxScaler

i = 0
scaler_ti = MinMaxScaler()
test_inputs = []
test_inputs = np.array(test_inputs)
temp_in = pd.read_excel(r'K:BachelorThesisDataTestingDataMix_Data_inputs.xlsx')
test_inputs = temp_in.to_numpy()
rows = test_inputs.shape[0]
scaler_ti.fit(test_inputs)
normalized_test_inputs = scaler_ti.transform(test_inputs)


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ''
port = 62402
s.bind((host,port))
s.listen(5)

while True:

    connection, clientsocket, address = s.accept()
    print(f"connection from {address} has been established!")
    strg = test_inputs
    temp = strg.tobytes()
    clientsocket.send(temp)
    clientsocket.close()

    if i in range(65533):
        i = i + 1
        msg = connection.recv(64)
        out = np.frombuffer(msg)
        inverse = scaler_ti.inverse_transform(out.reshape(1,8))
        print(inverse)

这是client.py

import socket
import numpy as np
import pandas as pd
import sklearn
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import load_model
import tensorflow as tf
from random import randint

i = 0
final = []
final = np.array(final)
#modelLSTM = load_model('K:BachelorThesiscode testingTireForces.LSTM/LSTM_model.h5')

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 62402
s.connect((host, port))

while True:
    if i in range(65533):
        i = i + 1
        msg = s.recv(64)
        out = np.frombuffer(msg)
        #out = out.reshape(1,8)
        #out = out.reshape(1,1,8)
        #prediction = modelLSTM.predict(out)
        #inverse = scaler_ti.inverse_transform(prediction.reshape(1,8))
        #print(prediction)
        #print(inverse)
        final = np.vstack(out) 
        print(out)
        if len(msg) <= 0:
             break
    strg = final
    temp = strg.tobytes()
    s.send(temp)
    #serversocket.close()
#print (final)

这是我从server.py收到的错误

Traceback (most recent call last):
  File "K:BachelorThesiscode testingserver.py", line 26, in <module>
    connection, clientsocket, address = s.accept()
ValueError: not enough values to unpack (expected 3, got 2)

这是我从client.py收到的错误

Traceback (most recent call last):
  File "K:BachelorThesiscode testingclient.py", line 31, in <module>
    final = np.vstack(out)
  File "<__array_function__ internals>", line 5, in vstack
  File "C:UserskarimAppDataLocalProgramsPythonPython39libsite- 
packages
umpycoreshape_base.py", line 283, in vstack
    return _nx.concatenate(arrs, 0)
  File "<__array_function__ internals>", line 5, in concatenate
ValueError: need at least one array to concatenate

解决方案

您的主要问题是accept()始终只发送两个值,但您需要三个值。

应该是

 connection, address = s.accept()

并且您应该使用connection而不是clientsocket


但它会带来其他问题,因为您在发送数据后关闭clientsocket,但您还需要此连接才能接收数据。

所有这一切看起来像是你加入了两个代码。这些代码可以单独工作,但不能一起工作-因为这两个代码都需要关闭连接以通知数据已结束,但现在您在发送后无法关闭它,因为您需要连接才能接收其他数据。

您必须使用不同的方式通知对方数据已结束。您必须首先发送数据大小(作为具有恒定大小的对象,因此作为字符串发送将不起作用,因为对于不同的数字,它可能具有不同的长度),然后再发送数据。然后另一端必须首先获取数据大小(作为具有恒定大小的对象),然后使用该si值来检测它是否获取了所有数据。

您可以使用structinteger大小转换为4个字节(因此,对于不同的值,它的大小是恒定的),而另一端必须读取4个字节,然后再次使用struct将其转换回integer

我无法运行它,但以下是代码。

服务器:

import socket
import struct

import numpy as np
import pandas as pd
import sklearn
from sklearn.preprocessing import MinMaxScaler

# --- functions ---

def send_data(connection, data):
    data_size = len(data)
    data_size_as_4_bytes = struct.pack('>I', data_size)
    
    connection.send(data_size_as_4_bytes)    
    connection.send(data)

def recv_data(connection, chunk_size=64):
    data_size_as_4_bytes = connection.recv(4)
    data_size = struct.unpack('>I', data_size_as_4_bytes)[0]
    
    data = b""
    size = 0

    while size < data_size:
        chunk = connection.recv(chunk_size)
        size += len(chunk)
        data += chunk
    
    return data

# --- main ---

scaler_ti = MinMaxScaler()

temp_in = pd.read_excel(r'K:BachelorThesisDataTestingDataMix_Data_inputs.xlsx')

test_inputs = temp_in.to_numpy()
rows = test_inputs.shape[0]

scaler_ti.fit(test_inputs)
normalized_test_inputs = scaler_ti.transform(test_inputs)

# -- send ---

HOST = ''  # or '0.0.0.0'
PORT = 62402

#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s = socket.socket()  # default values are `socket.AF_INET, socket.SOCK_STREAM`
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # solution for '[Error 89] Address already in use'. Use before bind()
s.bind((HOST, PORT))
s.listen(5)

try:
    while True:
        print('Waiting for client')

        # wait for new client
        connection, address = s.accept()
        print(f"connection from {address} has been established!")
        
        # --- send data ---
        
        print('send:', test_inputs)
        
        data = test_inputs.tobytes()
        send_data(connection, data)
        
        # don't close it because it is needed to receive data
        #clientsocket.close()

        # --- receive data ---

        data = recv_data(connection)
        output_data = np.frombuffer(data)
        
        print('recv:', output_data)

        # --- now you can close ---

        connection.close()
        
except KeyboardInterrupt:
    print("Stopped by Ctrl+C")
finally:
    s.close()
        

客户端:

import socket
import struct

import numpy as np
import pandas as pd
import sklearn
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import load_model
import tensorflow as tf
from random import randint

# --- functions ---

def send_data(connection, data):
    data_size = len(data)
    data_size_as_4_bytes = struct.pack('>I', data_size)
    
    connection.send(data_size_as_4_bytes)    
    connection.send(data)

def recv_data(connection, chunk_size=64):
    data_size_as_4_bytes = connection.recv(4)
    data_size = struct.unpack('>I', data_size_as_4_bytes)[0]
    
    data = b""
    size = 0

    while size < data_size:
        chunk = connection.recv(chunk_size)
        size += len(chunk)
        data += chunk
    
    return data

def some_calcuations(input_data)

    # need something different
    output_data = input_data
    
    return output_data

# --- main ---

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 62402
s.connect((host, port))

# --- recv ---

data = recv_data(s)
input_data = np.frombuffer(msg)

print('recv:', input_data)

# --- calculations ---

output_data = some_calcuations(input_data)

# --- send ---

print('send:', output_data)

data = output_data.tobytes()
send_data(s, data)

# --- close ---

s.close()

btw:

上周出现了类似的问题,我在其中显示了工作代码-它还使用threading同时为多个客户端运行服务器。

GUI运行时使用Socket发送图片(截图):
not responding in tkinter when click button completely

使用套接字发送泡菜:
Pickle data truncated

在服务器的线程中使用套接字,以便与多个客户端协同工作:
How to handle multithreading with sockets in Python?


编辑:

循环发送的版本。

在所有行之后,它发送单词end以通知已结束数据。

或者它可以在数据之前发送行数。

服务器:

import socket
import numpy as np

import struct

# --- functions ---

def send_data(connection, data):
    data_size = len(data)
    data_size_as_4_bytes = struct.pack('>I', data_size)
    
    connection.send(data_size_as_4_bytes)    
    connection.send(data)

def recv_data(connection, chunk_size=64):
    data_size_as_4_bytes = connection.recv(4)
    data_size = struct.unpack('>I', data_size_as_4_bytes)[0]
    
    data = b""
    size = 0

    while size < data_size:
        chunk = connection.recv(chunk_size)
        size += len(chunk)
        data += chunk
    
    return data

# --- main ---

np.random.seed(0)  # it will always gives the same random numbers
test_inputs = np.random.random_sample((3,5))

# -- send ---

HOST = ''  # or '0.0.0.0'
PORT = 62402

#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s = socket.socket()  # default values are `socket.AF_INET, socket.SOCK_STREAM`
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # solution for '[Error 89] Address already in use'. Use before bind()
s.bind((HOST, PORT))
s.listen(5)

try:
    while True:
        # --- wait for new client ---

        print('Waiting for client')
        
        connection, address = s.accept()
        print(f"Connection from {address} has been established!")

        # --- send ---
        
        for row in test_inputs:
        
            # --- send data ---
            
            print('send:', row)
            
            data = row.tobytes()
            send_data(connection, data)

            # --- receive data ---

            data = recv_data(connection)
            row = np.frombuffer(data)
            
            print('recv:', row)

        # information that it is end of data 
        send_data(connection, 'end'.encode())

        # --- now you can close ---
        
        connection.close()
        
except KeyboardInterrupt:
    print("Stopped by Ctrl+C")
finally:
    s.close()

客户端:


# author: Bartlomiej "furas" Burek (https://blog.furas.pl)
# date: 2021.07.23
#
# title: receiving back data from the client
# url: https://stackoverflow.com/questions/68499599/receiving-back-data-from-the-client/68502806#68502806

import socket
import numpy as np
from random import randint

import struct

# --- functions ---

def send_data(connection, data):
    data_size = len(data)
    data_size_as_4_bytes = struct.pack('>I', data_size)
    
    connection.send(data_size_as_4_bytes)    
    connection.send(data)

def recv_data(connection, chunk_size=64):
    data_size_as_4_bytes = connection.recv(4)
    data_size = struct.unpack('>I', data_size_as_4_bytes)[0]
    
    data = b""
    size = 0

    while size < data_size:
        chunk = connection.recv(chunk_size)
        size += len(chunk)
        data += chunk
    
    return data

def some_calcuations(input_data):

    # need something different
    output_data = input_data
    
    return output_data

# --- main ---

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 62402
s.connect((host, port))

while True:
    # --- recv ---

    data = recv_data(s)

    if data == b'end':
        break

    input_data = np.frombuffer(data)

    print('recv:', input_data)

    # --- calculations ---

    output_data = some_calcuations(input_data)

    # --- send ---

    print('send:', output_data)
    
    data = output_data.tobytes()
    send_data(s, data)

# --- close ---

s.close()

相关文章