Search code examples
pythonpandassocketstcpclient

How do you send .txt over TCP/IP line by line with a certain delay?


My code:

Client.py

import socket 
import pandas as pd 
import time
import pickle

# Load data
File = pd.read_csv('Data.txt', sep='\t', skipinitialspace=True, header=None, skiprows=1)

client_socket = socket.socket()
client_socket.connect(('localhost', 5555))  # Connect to server

client_socket.send(bytes("Sending file...", 'utf-8'))  # Note

Buffer = []

for x in range(File.shape[0]):
    count = 1
    Buffer = File.loc[count]
    client_socket.send(pickle.dumps(Buffer))
    count += 1
    time.sleep(2)  # Wait 2 sec

This is my server:

Server.py

import socket
import pickle 

server_socket = socket.socket()  
server_socket.bind(('localhost', 5555))  # local server-client

server_socket.listen(3) # Max. 3 connections
print('Waiting for connection')

Buffer = []
i = 0

while True:  
     client_socket, addr = server_socket.accept()  
     received_data = client_socket.recv(1024).decode()
     print('Client address', addr, received_data)

     client_socket.recv(pickle.loads(Buffer)).decode()
     print(Buffer[i])
     i =+ 1

     if(i == 10000):
         client_socket.close()  # Closing server socket
     else: continue

I am stuck with the following error:

   BrokenPipeError: [Errno 32] Broken pipe

The problem is with SIGPIPE, because the connection is interrupted based on what I found, in case I managed to implement the pickle correctly.

Server error:

Traceback (most recent call last):
  File "/Users/David/PycharmProjects/DP1/Server.py", line 19, in <module>
    client_socket.recv(pickle.loads(Buffer))
TypeError: a bytes-like object is required, not 'list'

I expected that decode() decodes the received pickle in bytes format to readable format on the side of the server. pickle.loads uses only one argument, so I cannot specify any encoding such as utf-8.

.txt file was exported from Excel (tab spacing):

Data.txt

Time    Speed   R_Ax    Activation  Delay   KP
11:11:37    13,1    124,45  100 2   4
11:11:39    13,08   124,26  100 2   4
11:11:41    13,15   124,925 100 2   4
11:11:43    13,08   124,26  100 2   4
11:11:45    13,11   124,545 100 2   4
11:11:47    13,13   124,735 100 2   4
11:11:49    13,13   124,735 100 2   4
11:11:51    13,05   123,975 100 2   4
11:11:53    13,07   124,165 100 2   4
11:11:55    13,11   124,545 0   2   999
11:11:57    13,1    124,45  0   2   999
11:11:59    13,06   124,07  0   2   999
11:12:01    13,07   124,165 0   2   999
11:12:03    12,99   123,405 0   2   999
11:12:05    13,03   123,785 0   2   999
11:12:07    13,05   123,975 0   2   999
11:12:09    13,11   124,545 0   2   999
11:12:11    13,04   123,88  0   2   999
11:12:13    13,04   123,88  0   2   999

Thank You.


Solution

  • Since you'd like to transfer a pandas series over the wire, one way to achieve this would be to use pickle. pickle can take a Series and convert it to a byte array, and then go in the other direction and convert a byte array to a series.

    On the client-side, use:

    client_socket.send(pickle.dumps(Buffer))
    

    Then, on the server-side use: pickle.loads

    Detailed answer

    The actual code on both sides would look like that:

    client:

    import socket
    import pandas as pd
    import time
    import pickle
    
    # Load data
    File = pd.read_csv('Data.txt', sep='\t', skipinitialspace=True, header=None, skiprows=1)
    
    client_socket = socket.socket()
    client_socket.connect(('localhost', 5555))  # Connect to server
    
    client_socket.send(bytes("Sending file...", 'utf-8'))  # Note
    
    Buffer = []
    
    for inx in range(File.shape[0]):
        Buffer = File.loc[inx]
        print(f"Sending \n {Buffer}")
        client_socket.send(pickle.dumps(Buffer))
        time.sleep(2)  # Wait 2 sec
    

    Server:

    import socket
    import pickle
    
    server_socket = socket.socket()
    server_socket.bind(('localhost', 5555))  # local server-client
    
    server_socket.listen(3) # Max. 3 connections
    print('Waiting for connection')
    
    Buffer = []
    i = 0
    
    client_socket, addr = server_socket.accept()
    received_data = client_socket.recv(1024)
    print('Client address', addr, received_data)
    
    while True:
         received_data = client_socket.recv(10000)
    
         Buffer.append(pickle.loads(received_data))
         print(Buffer[i])
         i =+ 1
    
    client_socket.close()  # Closing server socket (we'll never get here)