I am creating a very simple rdt 2.2 socket program that transfers an image file dictated as "Cat.bmp" from client to server. Once the client reads the first line of data from the bmp file, it sends it to the server, and then the server will continue to repeat reading this same line in an infinite loop. I have no idea why this won't allow the client to send new data. Any suggestions on how to fix this would be very appreciated.
Client.py
import binascii
import struct
import sys
import hashlib
import base64
import time
from asyncio.tasks import sleep
def rdtSend(currentSequence , currentAck , data):
values = (currentACK, currentSequence, data)
UDPData = struct.Struct('I I 8s')
packedData = UDPData.pack(*values)
checksumVal = hashlib.md5(packedData).hexdigest().encode('utf-8')
sendPacket = makepacket(currentACK, currentSequence, data, checksumVal)
UDPSend(sendPacket)
def makepacket(currentACK, currentSequence, data, checksumVal):
values = (currentACK, currentSequence, data, checksumVal)
packetData = struct.Struct('I I 8s 32s')
packet = packetData.pack(*values)
return packet
def UDPSend(sendPacket):
senderSocket.sendto(sendPacket, (IP, Port))
def dataError(receivePacket):
checksum = makeChecksum(receivePacket[0], receivePacket[1], receivePacket[2])
# Compare calculated chechsum with checksum value in packet
if receivePacket[3] == checksum:
print('CheckSums is OK')
return False
else:
print('CheckSums Do Not Match')
return True
def makeChecksum(ACK, SEQ, DATA):
values = (ACK, SEQ, DATA)
packer = struct.Struct('I I 8s')
packedData = packer.pack(*values)
checksum = hashlib.md5(packedData).hexdigest().encode('utf-8')
return checksum
def isACK(receivePacket, ACKVal):
if (receivePacket[0] == ACKVal):
return True
else:
return False
IP = "127.0.0.1"
#Local Port for client and server
Port = 20001
#buffer to receive information from client
bufferSize = 1024
unpacker = struct.Struct('I I 8s 32s')
senderSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
senderSocket.connect((IP , Port))
print("UDP IP:", IP)
print("UDP port:", Port)
filename = 'Cat.bmp'
file = open(filename , 'rb')
# current data item being processed
data = file.read(bufferSize)
currentSequence = 0
currentACK = 0
while (data):
rdtSend(currentSequence, currentACK , data)
packet, addr = senderSocket.recvfrom(bufferSize)
print(packet)
print("Received from: ", addr)
receivePacket = unpacker.unpack(packet)
if(dataError(receivePacket) == False and isACK(receivePacket , currentACK) == True):
currentACK = currentACK + 1
currentSequence = (currentSequence + 1) % 2
data = file.read(bufferSize)
print("sending more data")
else:
print("Resending packet")
file.close()
senderSocket.close
Server.py
import socket
import binascii
import struct
import sys
import hashlib
import base64
import time
from asyncio.tasks import sleep
def rdtSend(currentSequence , currentAck , data):
values = (currentACK, currentSequence, data)
UDPData = struct.Struct('I I 8s')
packedData = UDPData.pack(*values)
checksumVal = hashlib.md5(packedData).hexdigest().encode('utf-8')
#This is where it gets the UDP packet
sendPacket = makepacket(currentACK, currentSequence, data, checksumVal)
UDPSend(sendPacket)
def makepacket(currentACK, currentSequence, data, checksumVal):
values = (currentACK, currentSequence, data, checksumVal)
packetData = struct.Struct('I I 8s 32s')
packet = packetData.pack(*values)
return packet
def UDPSend(sendPacket):
receiverSocket.sendto(sendPacket, (IP, Port))
def makeChecksum(ACK, SEQ, DATA):
values = (ACK, SEQ, DATA)
packer = struct.Struct('I I 8s')
packedData = packer.pack(*values)
checksum = hashlib.md5(packedData).hexdigest().encode('utf-8')
return checksum
#Function that checks the packet for corruption
def dataError(receivePacket):
# Calculate new checksum of the [ ACK, SEQ, DATA ]
checksum = makeChecksum(receivePacket[0], receivePacket[1], receivePacket[2])
# Compare calculated chechsum with checksum value in packet
if receivePacket[3] == checksum:
print('CheckSums is OK')
return False
else:
print('CheckSums Do Not Match')
return True
#IP Address for local communications
IP = "127.0.0.1"
#Local Port for client and server
Port = 20001
#buffer to receive information from client
bufferSize = 1024
# Integer, Integer, 8 letter char array, 32 letter char array
unpacker = struct.Struct('I I 8s 32s')
# Create the actual UDP socket for the server
receiverSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the local IP address and port
receiverSocket.bind((IP, Port))
currentACK = 0
currentSequence = 0
dataFile = open('receive.bmp' , 'wb')
print("Listening")
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
#Where the previous functions are used to send the packets back to the client
while receivedPacket[2]:
print("Received from:", addr)
print("Data Received:" , receivedPacket[2])
#This compares checksums to see if there are errors
if not dataError(receivedPacket):
dataFile.write(receivedPacket[2])
# Built checksum [ACK, SEQ, DATA]
ACK = receivedPacket[0]
SEQ = receivedPacket[1]
DATA = b''
print('Packeting')
rdtSend(currentSequence , currentACK , DATA)
print('Sent')
currentACK = currentACK + 1
currentSequence = (currentSequence + 1) % 2
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
else:
print('Packet error')
checksumVal = makeChecksum(packet[0] + 1, (packet[1] + 1) % 2, b'')
packet = makepacket(packet[0] + 1, (packet[1] + 1) % 2, b'', checksumVal)
print('Packeting')
receiverSocket.sendto(packet, addr)
print('Sent')
packet, addr = receiverSocket.recvfrom(bufferSize)
receivedPacket = unpacker.unpack(packet)
dataFile.close()
receiverSocket.close```
Related
I sent a scaled array using socket connection from the server to the client and it worked well now I wanted to send back the data to the server to unscale it in the server. The data is sent to the client each row at a time so I try to put them back in order in an empty array called final.
This is the 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:\BachelorThesis\Data\TestingData\Mix_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)
This is the 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:\BachelorThesis\code testing\TireForces.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)
This is the error I get from the server.py
Traceback (most recent call last):
File "K:\BachelorThesis\code testing\server.py", line 26, in <module>
connection, clientsocket, address = s.accept()
ValueError: not enough values to unpack (expected 3, got 2)
This is the error I get from the client.py
Traceback (most recent call last):
File "K:\BachelorThesis\code testing\client.py", line 31, in <module>
final = np.vstack(out)
File "<__array_function__ internals>", line 5, in vstack
File "C:\Users\karim\AppData\Local\Programs\Python\Python39\lib\site-
packages\numpy\core\shape_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
Your main problem is that accept() always sends only two values but you expect three.
It should be
connection, address = s.accept()
and you should use connection instead of clientsocket
But it will give other problem because you close clientsocket after sending data but you need this connection also to receive data.
All this looks like you joined two codes. These codes could work separatelly but it will not work together - because both needs to close connection to inform that this is end of data but now you can't close it after sending because you need connection to receive other data.
You have to use different way to inform other side that it is end of data. You have to first send data size (as object with constant size so sending as string will not work because it may have different length for different numbers) and later send data. And then other side has to first get data size (as object with constant size) and later use thsi value to detect if it get all data.
You can use struct to convert integer size to 4 bytes (so it will have constant size for different values) and other side will have to read 4 bytes and use again struct to convert back to integer
I can't run it but here is code.
Server:
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:\BachelorThesis\Data\TestingData\Mix_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()
Client:
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:
Last week there was similar question where I show working code - and it also use threading to run server for many clients at the same time.
Use socket to send image (screenshot) when GUI is runnig:
not responding in tkinter when click button completely
Use socket to send pickle:
Pickle data truncated
Use socket in threading in server to work with many clients:
How to handle multithreading with sockets in Python?
EDIT:
Version which send in loop.
After all rows it sends word end to inform that it is end of data.
Or it could send number of rows before data.
Server:
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()
Client:
# 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()
I have a code which is running on 2 hosts. They are processing some photos. When host1 receives a message, it will send some of its photos to host2 for processing. It will also send a list to host2 (it will convert it to string and then it will send it).
import pickle
import time, threading
host = commands.getoutput("hostname -I")
port = 5005
i = 0
backlog = 5
BUFSIZE = 4096
queueList = []
start = []
end = []
l = threading.Lock()
def read_udp(s):
data,addr = s.recvfrom(1024)
global start
if data.startswith('10.0.0'):
print("received message:", data)
data_split = data.split(" ")
address = data_split[0]
num = int(data_split[1])
ipToTransfer = address
l.acquire()
transferList = queueList[-num:]
del queueList[-num:]
transferStart = start[-num:]
del start[-num:]
l.release()
msg = pickle.dumps(transferStart)
#udp_send('New Transfer', ipToTransfer)
udp_send(msg, ipToTransfer)
send_file(ipToTransfer, transferList)
else:
recvStart = pickle.loads(data)
print("start before add::: ", start)
print("received::: ", recvStart)
l.acquire()
start = start + recvStart
l.release()
print("start after add::: ", start)
def udp_send(s, ip):
UDP_IP = ip
if(type(s) == str):
MESSAGE = s
else:
MESSAGE = pickle.dumps(s)
#print(MESSAGE)
print ("UDP target IP & port:", UDP_IP, port)
print ("message:", MESSAGE)
sock3 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock3.sendto(MESSAGE, (UDP_IP, port))
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def send(sock2, data2):
while data2:
sent = sock2.send(data2)
data2 = data2[sent:]
def send_file(ipToTransfer, transferList):
while transferList:
fname = transferList.pop(0)
print("transferring:", fname)
with open(fname, 'rb') as f:
sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock2.connect((ipToTransfer, 5005))
except socket.error as err:
print(err, ipToTransfer, 5005)
sock2.close()
return
# Send the file name length & the filename itself in one packet
send(sock2, pack('B', len(fname)) + fname.encode())
while True:
data2 = f.read(BUFSIZE)
if not data2:
break
send(sock2, data2)
sock2.close()
When host2 receives this string, it will convert it to list again, but I receive an EOFError in this part. My cmd doesn't have the copy capability, so I upload the photo from this error:
What's wrong?
you delete the pointer to what is being pickled
transferStart = start[-num:]
del start[-num:]
l.release()
msg = pickle.dumps(transferStart)
If you are trying to remove elements from a list that is not the way to do it. Consider popping or reassigning into another list that does not have that element, etc.
Recently I wrote some code (client and server) to send an image - the client simply uploads the image to the server, just using the socket module: Sending image over sockets (ONLY) in Python, image can not be open.
However, the image sending part is now what I am concerned with. This is the original image I'm using:
In my server code (which receives the images), I have these lines:
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
But I don't think this is the best way of doing it. I think I should instead implement the server such that it receives the data in chunks:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 2905
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if data:
if data.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size %s' % size
sock.sendall("GOT SIZE")
elif data.startswith('BYE'):
sock.shutdown()
else :
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
amount_received = 0
while amount_received < size:
data = sock.recv(4096)
amount_received += len(data)
print amount_received
if not data:
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
But when I do this, the server prints:
got size 54674
4096
8192
12288
16384
20480
24576
28672
32768
36864
40960
45056
49152
50578
And then seems to hang, and the client hangs too. However, at the server's side I can see only a piece of the image the client wanted to send:
It seems like there are some bytes missing. What is the proper way of sending a huge amount of data (images, other type of file) using ONLY sockets?
I'm assuming that you have a particular reason for doing this with naked sockets, such as self-edification, which means that I won't answer by saying "You accidentally forgot to just use HTTP and Twisted", which perhaps you've heard before :-P. But really you should look at higher-level libraries at some point as they're a lot easier!
Define a protocol
If all you want is to send an image, then it can be simple:
Client -> server: 8 bytes: big endian, length of image.
Client -> server: length bytes: all image data.
(Client <- server: 1 byte, value 0: indicate transmission received - optional step you may not care if you're using TCP and just assume that it's reliable.)
Code it
server.py
import os
from socket import *
from struct import unpack
class ServerProtocol:
def __init__(self):
self.socket = None
self.output_dir = '.'
self.file_num = 1
def listen(self, server_ip, server_port):
self.socket = socket(AF_INET, SOCK_STREAM)
self.socket.bind((server_ip, server_port))
self.socket.listen(1)
def handle_images(self):
try:
while True:
(connection, addr) = self.socket.accept()
try:
bs = connection.recv(8)
(length,) = unpack('>Q', bs)
data = b''
while len(data) < length:
# doing it in batches is generally better than trying
# to do it all in one go, so I believe.
to_read = length - len(data)
data += connection.recv(
4096 if to_read > 4096 else to_read)
# send our 0 ack
assert len(b'\00') == 1
connection.sendall(b'\00')
finally:
connection.shutdown(SHUT_WR)
connection.close()
with open(os.path.join(
self.output_dir, '%06d.jpg' % self.file_num), 'w'
) as fp:
fp.write(data)
self.file_num += 1
finally:
self.close()
def close(self):
self.socket.close()
self.socket = None
# could handle a bad ack here, but we'll assume it's fine.
if __name__ == '__main__':
sp = ServerProtocol()
sp.listen('127.0.0.1', 55555)
sp.handle_images()
client.py
from socket import *
from struct import pack
class ClientProtocol:
def __init__(self):
self.socket = None
def connect(self, server_ip, server_port):
self.socket = socket(AF_INET, SOCK_STREAM)
self.socket.connect((server_ip, server_port))
def close(self):
self.socket.shutdown(SHUT_WR)
self.socket.close()
self.socket = None
def send_image(self, image_data):
# use struct to make sure we have a consistent endianness on the length
length = pack('>Q', len(image_data))
# sendall to make sure it blocks if there's back-pressure on the socket
self.socket.sendall(length)
self.socket.sendall(image_data)
ack = self.socket.recv(1)
# could handle a bad ack here, but we'll assume it's fine.
if __name__ == '__main__':
cp = ClientProtocol()
image_data = None
with open('IMG_0077.jpg', 'r') as fp:
image_data = fp.read()
assert(len(image_data))
cp.connect('127.0.0.1', 55555)
cp.send_image(image_data)
cp.close()
A simple way is to send data size as the first 4 bytes of your data and then read complete data in one shot. Use the below functions on both client and server-side to send and receive data.
def send_data(conn, data):
serialized_data = pickle.dumps(data)
conn.sendall(struct.pack('>I', len(serialized_data)))
conn.sendall(serialized_data)
def receive_data(conn):
data_size = struct.unpack('>I', conn.recv(4))[0]
received_payload = b""
reamining_payload_size = data_size
while reamining_payload_size != 0:
received_payload += conn.recv(reamining_payload_size)
reamining_payload_size = data_size - len(received_payload)
data = pickle.loads(received_payload)
return data
you could find sample program at https://github.com/vijendra1125/Python-Socket-Programming.git
The problem is you are not incrementing amount_received for the first chunk of the data received.
Fix below:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 2905
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if data:
if data.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size %s' % size
sock.sendall("GOT SIZE")
elif data.startswith('BYE'):
sock.shutdown()
else :
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
amount_received = len(data) # The fix!
while amount_received < size:
data = sock.recv(4096)
amount_received += len(data)
print amount_received
if not data:
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
The following is complete client , server and sendproc codes:
Client.py
from socket import *
import pickle
import sendproc
import struct
s = socket(AF_INET, SOCK_STREAM) # Create a socket object
host = "192.168.1.4" # Get local machine name
port = 1094 # Reserve a port for your service.
s.connect((host, port))
with open("file.txt",'rb') as f:
print ('file opened')
print('Sending file...')
for data in f:
print(data)
print("MSG sent")
sendproc.send_msg(s, data)
Server.py
from socket import *
import pickle
import sendproc
port = 1094 # Reserve port for service.
s = socket(AF_INET,SOCK_STREAM) # Create a socket object
host = "192.168.1.4" # Get local machine name
s.bind((host, port)) # Bind to the port
s.listen(5)
print('server is listening')
conn,addr = s.accept()
with open("file1.txt",'w') as fb:
print("File downloading\n",fb)
while True:
print("hi")
data = sendproc.recv_msg(conn)
print(data)
if not data:
print("No data")
break
fb.write(data)
fb.flush()
print("Download complete\n")
SendRecieveProcedure.py
import struct
def send_msg(s, msg):
msg2 = struct.pack('>I', len(msg)) + msg
s.send(msg2)
def recv_msg(s):
# Read message length and unpack it into an integer
raw_msglen = s.recv(4)
print(raw_msglen)
if not raw_msglen:
return None
n = struct.unpack('>I',raw_msglen)[0]
# Read the message data
data = ' '
while len(data) < n:
packet = s.recv(n - len(data)).decode("cp437")
if not packet:
return None
data += packet
#print("hwllo",data )
return data
output prints correctly to the console, but if I go open up the file it's only writing starting lines.so what is the problem in code
I wanted to write simple udp port scanner on python and I faced some problems.
First of all am I understand right that there are 3 options:
send UDP - get nothing -> port is filtered|opened
send UDP - get icmp port unreachable -> port is closed
send UDP - get UDP - port is opened
I create raw socket, create ip header and udp header. In udp header write the dest port and add some data.
Then I send it to server and with select wait for a reply. But nothing neither on opened port nor on closed. Only timeout.
And is it possible to send just dummy data but not correct packet of the next level ?
[Update 1]
Added more data to send in udp packet. Now I get udp packet back from (194.226.244.126, 53) but my host send back icmp type 3 to 194.226.244.126 before I could read any recieved data. But still no response from 8.8.8.8
[Update 2]
Found that 8.8.8.8 reply only on correct dns packets. But still can't read udp packet with raw socket.
import socket
import time
import select
import sys
from packets_headers import iphdr, udphdr
from get_ip import Getip
timeout = 3
host = "8.8.8.8"
port = 53
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW)
udp_header = udphdr(b"00000000000000000", port, 4242)
udp_packet = udp_header.assemble()
g = Getip()
ip_packet_header = iphdr(socket.IPPROTO_UDP, g.get_lan_ip(), host)
ip_packet_header.data = udp_packet
ip_packet = ip_packet_header.assemble()
my_socket.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
full_packet = ip_packet
while full_packet:
sent = my_socket.sendto(full_packet, (host, port))
full_packet = full_packet[sent:]
ready = select.select([my_socket], [], [], timeout)
if ready[0] == []: # Timeout
print("Timeout")
sys.exit()
rec_packet, addr = my_socket.recvfrom(1024)
print(rec_packet, addr)
Also packets_header.py
import socket
import struct
import random
class iphdr(object):
"""
This represents an IP packet header.
#assemble packages the packet
#disassemble disassembles the packet
"""
def __init__(self, proto=socket.IPPROTO_ICMP, src="0.0.0.0", dst=None):
self.version = 4
self.hlen = 5
self.tos = 0
self.length = 20
self.id = random.randint(2 ** 10, 2 ** 16)
self.frag = 0
self.ttl = 255
self.proto = proto
self.cksum = 0
self.src = src
self.saddr = socket.inet_aton(src)
self.dst = dst or "0.0.0.0"
self.daddr = socket.inet_aton(self.dst)
self.data = ""
def assemble(self):
header = struct.pack('BBHHHBB',
(self.version & 0x0f) << 4 | (self.hlen & 0x0f),
self.tos, self.length + len(self.data),
socket.htons(self.id), self.frag,
self.ttl, self.proto)
self._raw = header + b"\x00\x00" + self.saddr + self.daddr + self.data
return self._raw
#classmethod
def disassemble(self, data):
self._raw = data
ip = iphdr()
pkt = struct.unpack('!BBHHHBBH', data[:12])
ip.version = (pkt[0] >> 4 & 0x0f)
ip.hlen = (pkt[0] & 0x0f)
ip.tos, ip.length, ip.id, ip.frag, ip.ttl, ip.proto, ip.cksum = pkt[1:]
ip.saddr = data[12:16]
ip.daddr = data[16:20]
ip.src = socket.inet_ntoa(ip.saddr)
ip.dst = socket.inet_ntoa(ip.daddr)
return ip
def __repr__(self):
return "IP (tos %s, ttl %s, id %s, frag %s, proto %s, length %s) " \
"%s -> %s" % \
(self.tos, self.ttl, self.id, self.frag, self.proto,
self.length, self.src, self.dst)
class udphdr(object):
def __init__(self, data="", dport=4242, sport=4242):
self.dport = dport
self.sport = sport
self.cksum = 0
self.length = 0
self.data = data
def assemble(self):
self.length = len(self.data) + 8
part1 = struct.pack("!HHH", self.sport, self.dport, self.length)
cksum = self.checksum(self.data)
cksum = struct.pack("!H", cksum)
self._raw = part1 + cksum + self.data
return self._raw
#classmethod
def checksum(self, data):
# XXX implement proper checksum
cksum = 0
return cksum
def disassemble(self, data):
self._raw = data
udp = udphdr()
pkt = struct.unpack("!HHHH", data)
udp.src_port, udp.dst_port, udp.length, udp.cksum = pkt
return udp