tcp lost packet python [duplicate] - python

This question already exists:
TCP socket python
Closed 2 years ago.
i am using tcp socket for forwarding data (as class with type of request, and data) between server and client. When i send 6 object of order from client, the server get only 5 object of order, 1 is lost, but tcp is reliable protocol... (sometimes the server get 6 but usually get 5) my question is why an object lost in forwarding by tcp?
Here's the client code
PORT = 3000
SIZE = 4096
HOST = '127.0.0.1'
soc = None
ing_map = None
def connect_to_client():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
global soc
soc = s
def send_object(data):
if soc is None:
raise NotImplementedError # There is no connection
else:
# make data as bytes
msg = pickle.dumps(data)
msg = bytes(f"{len(msg):<{HEADERSIZE}}", 'utf-8') + msg
print(sys.getsizeof(msg))
soc.send(msg)
def get_object(req):
if soc is None:
raise NotImplementedError # There is no connection
else:
# unpickle the data
send_object(req)
if soc is None:
raise NotImplementedError # There is no connection
else:
# unpickle the data
data = b''
while True:
part = soc.recv(SIZE)
data += part
if len(part) < SIZE:
break
full_msg = data
try:
data = pickle.loads(full_msg[HEADERSIZE:])
except EOFError:
data = None
return data
def send_order(order):
if order is not None:
send_object(Soc_request(Request.P_ORDER,order))
def main():
global ing_map
connect_to_client()
ing_map = get_object(Soc_request(Request.G_ING_MAP, None))
#send order
burger = Burger(ing_map)
salad = Salad(ing_map)
burger.add_ingredient('ham')
o1 = Order(Priority.NORMAL)
o2 = Order(Priority.NORMAL)
o3 = Order(Priority.VIP)
o4 = Order(Priority.VIP)
o5 = Order(Priority.PLUS)
o6 = Order(Priority.PLUS)
o1.meals_lst.append(burger)
o1.meals_lst.append(burger)
o1.meals_lst.append(burger)
o3.meals_lst.append(burger)
send_order(o1)
send_order(o2)
send_order(o3)
send_order(o4)
send_order(o5)
send_order(o6)
soc.close()
Here's the server code
HOST = '127.0.0.1'
PORT = 3000
SIZE = 1000
HEADERSIZE = 10
WORKERS = 2
conn = None
addr = None
soc = None
order_m = None
def create_connection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
global conn, addr
global soc
soc = s
conn, addr = s.accept()
def send_object(data):
if soc is None:
raise NotImplementedError # There is no connection
else:
# make data as bytes
global conn
msg = pickle.dumps(data)
msg = bytes(f"{len(msg):<{HEADERSIZE}}", 'utf-8') + msg
conn.send(msg)
def get_object():
global conn
if conn is None:
raise NotImplementedError # There is no connection
else:
# unpickle the data
data = b''
while True:
part = conn.recv(SIZE)
data += part
if len(part) < SIZE:
break
full_msg = data
try:
data = pickle.loads(full_msg[HEADERSIZE:])
except EOFError:
data = None
return data
def main():
create_connection()
# Initialize objects
global order_m
ing_map = Ingredient_map()
order_m = OrderManager()
while True:
msg = get_object()
if msg is None:
pass
elif msg.req == Request.G_ING_MAP: # get ingredient map
send_object(ing_map.instance.map)
elif msg.req == Request.P_ORDER:
order_m.add_order(msg.data)
print(msg.data)
# end while
soc.close()
if __name__ == "__main__":
main()
The output of the server is
order 0
order 1
order 3
order 4
order 5
but order 2 lost!
why? what should i fix that all the orders will arrive ?
Request is an enum for request type.

Let's visualize the 6 pickled objects on their way from the client to the server:
server <- 1112222233334445555566 <- client
A TCP connection is one stream of data. There are no boundaries. The server has to split the data to individual parts and unpickle each part:
111 22222 3333 444 55555 66
In order to be able to do that, you must introduce some high level structure to the data. I can't run your code, but I don't see anything like that there. Instead the server just reads into a fixed size buffer. The reality is little bit complicated, but I think this is sometimes happening:
1112 2222 3333 4445 5555 66
The objects 1, 3, 4 and 6 were transferred in one piece, but 2 and 5 were divided into two parts and these parts cannot be separately unpickled.
I think you need to put the length of the pickled data to the header. Then the server should first read the header (fixed size), extract the length and then read and unpickle as many following bytes (not less, not more).
Also this fragment:
try:
data = pickle.loads(full_msg[HEADERSIZE:])
except EOFError:
data = None
hides errors. Do not blame TCP for losing packets when you silently discard data.

As #VPfB mentioned, you are sending the header size but never parsing the size. You really should restructure your code, however, here is a working example using your code.
In your client code, change your get_object function to this.
def get_object(req):
if soc is None:
raise NotImplementedError # There is no connection
else:
# unpickle the data
send_object(req)
if soc is None:
raise NotImplementedError # There is no connection
else:
# unpickle the data
# this initial recv only receives the header length
length = int(soc.recv(HEADERSIZE).decode('utf-8'))
data = b''
while True:
# here we receive a minimum of the standard recv size
# and the diff between your already received data
# and the full length, whichever is smaller
part = soc.recv(min(SIZE, length - len(data)))
data += part
# if the length that was specifed in the header has been received
# we know we have everything
if length == len(data):
break
full_msg = data
try:
data = pickle.loads(full_msg)
except EOFError:
data = None
return data
Now we'll make almost identical changes in your server code.
def get_object():
global conn
if conn is None:
raise NotImplementedError # There is no connection
else:
# unpickle the data
# the only difference here is
# when we receive nothing, we know it's time to wait for another connect
length = conn.recv(HEADERSIZE).decode('utf-8')
if len(length):
length = int(length)
data = b''
while True:
part = conn.recv(min(SIZE, length - len(data)))
data += part
if length == len(data):
break
full_msg = data
try:
data = pickle.loads(full_msg)
except EOFError:
data = None
return data
else:
# wait for another connection
conn, addr = soc.accept()
In reality a server typically behaves like this:
# do this forever
while True:
# wait for an incoming connection
conn, addr = soc.accept()
# get the length of the data the connection is sending
length = int(soc.recv(HEADERSIZE).decode('utf-8'))
# get the data
data = b''
while True:
part = soc.recv(min(SIZE, length - len(data)))
data += part
if length == len(data):
break
# do some stuff with the data
The difference is we wait for a fresh connection after each object received. This gives other clients attempting to connect a turn as well.

Related

Why can't I access a specific variable inside of a threaded class

The bounty expires in 5 days. Answers to this question are eligible for a +50 reputation bounty.
Haley Mueller wants to draw more attention to this question.
I'm new to Python so this could be a simple fix.
I am using Flask and sockets for this Python project. I am starting the socket on another thread so I can actively listen for new messages. I have an array variable called 'SocketConnections' that is within my UdpComms class. The variable gets a new 'Connection' appended to it when a new socket connection is made. That works correctly. My issue is that when I try to read 'SocketConnections' from outside of the thread looking in, it is an empty array.
server.py
from flask import Flask, jsonify
import UdpComms as U
app = Flask(__name__)
#app.route('/api/talk', methods=['POST'])
def talk():
global global_server_socket
apples = global_server_socket.SocketConnections
return jsonify(message=apples)
global_server_socket = None
def start_server():
global global_server_socket
sock = U.UdpComms(udpIP="127.0.0.1", portTX=8000, portRX=8001, enableRX=True, suppressWarnings=True)
i = 0
global_server_socket = sock
while True:
i += 1
data = sock.ReadReceivedData() # read data
if data != None: # if NEW data has been received since last ReadReceivedData function call
print(data) # print new received data
time.sleep(1)
if __name__ == '__main__':
server_thread = threading.Thread(target=start_server)
server_thread.start()
app.run(debug=True,host='192.168.0.25')
UdpComms.py
import json
import uuid
class UdpComms():
def __init__(self,udpIP,portTX,portRX,enableRX=False,suppressWarnings=True):
self.SocketConnections = []
import socket
self.udpIP = udpIP
self.udpSendPort = portTX
self.udpRcvPort = portRX
self.enableRX = enableRX
self.suppressWarnings = suppressWarnings # when true warnings are suppressed
self.isDataReceived = False
self.dataRX = None
# Connect via UDP
self.udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # internet protocol, udp (DGRAM) socket
self.udpSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # allows the address/port to be reused immediately instead of it being stuck in the TIME_WAIT state waiting for late packets to arrive.
self.udpSock.bind((udpIP, portRX))
# Create Receiving thread if required
if enableRX:
import threading
self.rxThread = threading.Thread(target=self.ReadUdpThreadFunc, daemon=True)
self.rxThread.start()
def __del__(self):
self.CloseSocket()
def CloseSocket(self):
# Function to close socket
self.udpSock.close()
def SendData(self, strToSend):
# Use this function to send string to C#
self.udpSock.sendto(bytes(strToSend,'utf-8'), (self.udpIP, self.udpSendPort))
def SendDataAddress(self, strToSend, guid):
# Use this function to send string to C#
print('finding connection: ' + guid)
if self.SocketConnections:
connection = self.GetConnectionByGUID(guid)
print('found connection: ' + guid)
if connection is not None:
self.udpSock.sendto(bytes(strToSend,'utf-8'), connection.Address)
def ReceiveData(self):
if not self.enableRX: # if RX is not enabled, raise error
raise ValueError("Attempting to receive data without enabling this setting. Ensure this is enabled from the constructor")
data = None
try:
data, _ = self.udpSock.recvfrom(1024)
print('Socket data recieved from: ', _)
if self.IsNewConnection(_) == True:
print('New socket')
self.SendDataAddress("INIT:" + self.SocketConnections[-1].GUID, self.SocketConnections[-1].GUID)
data = data.decode('utf-8')
except WindowsError as e:
if e.winerror == 10054: # An error occurs if you try to receive before connecting to other application
if not self.suppressWarnings:
print("Are You connected to the other application? Connect to it!")
else:
pass
else:
raise ValueError("Unexpected Error. Are you sure that the received data can be converted to a string")
return data
def ReadUdpThreadFunc(self): # Should be called from thread
self.isDataReceived = False # Initially nothing received
while True:
data = self.ReceiveData() # Blocks (in thread) until data is returned (OR MAYBE UNTIL SOME TIMEOUT AS WELL)
self.dataRX = data # Populate AFTER new data is received
self.isDataReceived = True
# When it reaches here, data received is available
def ReadReceivedData(self):
data = None
if self.isDataReceived: # if data has been received
self.isDataReceived = False
data = self.dataRX
self.dataRX = None # Empty receive buffer
if data != None and data.startswith('DIALOG:'): #send it info
split = data.split(':')[1]
return data
class Connection:
def __init__(self, gUID, address) -> None:
self.GUID = gUID
self.Address = address
def IsNewConnection(self, address):
for connection in self.SocketConnections:
if connection.Address == address:
return False
print('Appending new connection...')
connection = self.Connection(str(uuid.uuid4()),address)
self.SocketConnections.append(connection)
return True
def GetConnectionByGUID(self, guid):
for connection in self.SocketConnections:
if connection.GUID == guid:
return connection
return None
As mentioned above. When IsNewConnection() is called in UdpComms it does append a new object to SocketConnections. It's just trying to view the SocketConnections in the app.route that is empty. My plans are to be able to send socket messages from the app.routes
For interprocess communication you may try to use something like shared memory documented here
Instead of declaring your self.SocketConnections as a list = []
you'd use self.SocketConnections = Array('i', range(10)) (you are then limited to remembering only 10 connections though).

getting part of the recv() buffer

I have this code, that print the http server response, but now I'm trying to get the only the status code, and from there make decisions.
like :
Code:200 - print ok
code:404 - print page not found
etc
PS: cant use http library
from socket import *
#constants variables
target_host = 'localhost'
target_port = 80
target_dir = 'dashboard/index.html'
# create a socket object
client = socket(AF_INET, SOCK_STREAM) # create an INET (IPv4), STREAMing socket (TCP)
# connect the client
client.connect((target_host,target_port))
# send some data
request = "GET /%s HTTP/1.1\r\nHost:%s\r\n\r\n" % (target_dir, target_host)
#Send data to the socket.
client.send(request.encode())
# receive some data
data = b''
while True: #while data
buffer = client.recv(2048) #recieve a 2048 bytes data from socket
if not buffer: #no more data, break
break
data += buffer #concatenate buffer data
client.close() #close buffer
#display the response
print(data.decode())
I would change the reception loop as below: extract the first line, split it, interpret the second word as an integer.
line = b''
while True:
c = client.recv(1)
if not c or c=='\n':
break
line += c
status = -1
line = line.split()
if len(line)>=2:
try:
status = int(line[1])
except:
pass
print(status)
If we heavily rely on try we can simplify the second part
try:
status = int(line.split()[1])
except:
status = -1
print(status)

My TCP server only sends b' ' instead of the pickled data

I have a TCP server and a Kivy app client, upon initialisation I send the server code 90010 and get all the data fine however when I move to another screen where I need to receive data again I only receive b'' however on other screens I only need to send data and that works perfectly, I honestly can't wrap my head around why its sending empty byte strings any help is really appreciated
I know the code is reaching the if server code == 919 point so it should be sending the data but nothing is being received!, I have also put a s.connect on the initialisation of every screen maybe this is causing problems however im completely unsure
TCP code this SERVERCODE is in the class clientthread and it uses the same method as the client with GetLength() to get server code
class clientthread(thread)
def run(self)
while true:
SERVERCODE = self.getlength
if SERVERCODE == b''
break
else:
while true:
elif SERVERCODE == 90010:
global Todays_refgroup
print(Todays_refgroup)
print(statuslist)
TF_Pickles = pickle.dumps(Todays_refgroup)
INIT_Length = self.Pack_data(TF_Pickles)
TF_Status = pickle.dumps(statuslist)
INIT_Status = self.Pack_data(TF_Status)
conn.sendall(INIT_Length)
conn.sendall(TF_Pickles)
conn.sendall(INIT_Status)
conn.sendall(TF_Status)
break
elif SERVERCODE == 919:
pickle_status = pickle.dumps(statuslist)
len_statpick = self.Pack_data(pickle_status)
conn.sendall(len_statpick)
conn.sendall(pickle_status)
break
TCP_IP = '127.0.0.1'
TCP_PORT = 8079
BUFFER_SIZE = 1024
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpServer.listen(4)
print(" : Waiting for connections from TCP clients...")
(conn, (ip, port)) = tcpServer.accept()
newthread = ClientThread(ip, port)
newthread.start()
threads.append(newthread)
Client Code
servercode = StructPack(919)
self.s.sendall(servercode)
buf = GetLength(self.s)
stats = GetSpecificAmount(self.s, buf)
print(stats)
def GetLength(socket):
buf = b''
while len(buf) < 4:
# print('waiting...')
tbuf = socket.recv(4 - len(buf))
if tbuf == '':
raise RuntimeError("Lost connection with peer")
buf += tube
SERVERCODE = struct.unpack('!I', buf)[0]
return SERVERCODE
def GetSpecificAmount(socket, Amount_2Recieve):
data = []
len_recvd = 0
while len_recvd < Amount_2Recieve:
buf = socket.recv(Amount_2Recieve - len_recvd)
if buf == '':
raise RuntimeError("Lost connection with peer")
data.append(buf)
len_recvd += len(buf)
# print(len_recvd)
df = pickle.loads(b''.join(data))
return df

What is the proper way of sending a large amount of data over sockets in Python?

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

Socket Programming; File corrupts when transferring over multiple devices

The problem I'm having is to get a file from the server to client across devices. Everything works fine on localhost.
Lets say I want to "get ./testing.pdf" which sends the pdf from the server to the client. It sends but it is always missing bytes. Is there any problems with how I am sending the data. If so how can I fix it? I left out the code for my other functionalities since they are not used for this function.
sending a txt file with "hello" in it works perfectly
server.py
import socket, os, subprocess # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
#host = ''
port = 5000 # Reserve a port for your service.
bufsize = 4096
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
while True:
userInput = c.recv(1024)
.... CODE ABOUT OTHER FUNCTIONALITY
elif userInput.split(" ")[0] == "get":
print "inputed get"
somefile = userInput.split(" ")[1]
size = os.stat(somefile).st_size
print size
c.send(str(size))
bytes = open(somefile).read()
c.send(bytes)
print c.recv(1024)
c.close()
client.py
import socket, os # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
#host = '192.168.0.18'
port = 5000 # Reserve a port for your service.
bufsize = 1
s.connect((host, port))
print s.recv(1024)
print "Welcome to the server :)"
while 1 < 2:
userInput = raw_input()
.... CODE ABOUT OTHER FUNCTIONALITY
elif userInput.split(" ")[0] == "get":
print "inputed get"
s.send(userInput)
fName = os.path.basename(userInput.split(" ")[1])
myfile = open(fName, 'w')
size = s.recv(1024)
size = int(size)
data = ""
while True:
data += s.recv(bufsize)
size -= bufsize
if size < 0: break
print 'writing file .... %d' % size
myfile = open('Testing.pdf', 'w')
myfile.write(data)
myfile.close()
s.send('success')
s.close
I can see two problems right away. I don't know if these are the problems you are having, but they are problems. Both of them relate to the fact that TCP is a byte stream, not a packet stream. That is, recv calls do not necessarily match one-for-one with the send calls.
size = s.recv(1024) It is possible that this recv could return only some of the size digits. It is also possible that this recv could return all of the size digits plus some of the data. I'll leave it for you to fix this case.
data += s.recv(bufsize) / size -= bufsize There is no guarantee that that the recv call returns bufsize bytes. It may return a buffer much smaller than bufsize. The fix for this case is simple: datum = s.recv(bufsize) / size -= len(datum) / data += datum.

Categories

Resources