6

I am having the above issue. The client is suppose to ask for a filename and send the file name to the server after which the server will open the file and display it. Problem is that the server isn't opening the file and displaying it.

Below is the client.

#!/usr/bin/env python3 
import socket, os.path, datetime, sys

def Main():
    host = '127.0.0.1'
    port = 50001

    s = socket.socket()
    s.connect((host, port))

    Filename = input("Type in ur file ")
    s.send(Filename.encode('utf-8'))
    data = s.recv(1024).decode('utf-8')
    s.close()

if __name__ == '__main__':
    Main()

Below is the server

#!/usr/bin/env python3

import socket
import os
import sys



def Main():
    host = '127.0.0.1'
    port = 50001

    s = socket.socket()
    s.bind((host,port))
    print("server Started")
    s.listen(1)
    c, addr = s.accept()
    print("Connection from: " + str(addr))
    while True:
        data = c.recv(1024).decode('utf-8')
        myfile = open(data, "r")
        if not data:
            break
        print("from connected user: " + myfile)

    c.close()

if __name__ == '__main__':
    Main()
Ondrej K.
  • 8,841
  • 11
  • 24
  • 39
Crazytech
  • 63
  • 1
  • 1
  • 4
  • See this post to get an idea of how file transfer should be done: https://stackoverflow.com/q/27241804/1190388 – hjpotter92 Jul 25 '18 at 11:24

1 Answers1

3

I've made few minimal adjustments to your code with which it runs as so that server.py continuously listens on a given port and sends back data which each invocation of client.py asks for.

server.py

#!/usr/bin/env python3
import socket
import os
import sys

def Main():
    host = '127.0.0.1'
    port = 50001

    s = socket.socket()
    s.bind((host,port))
    print("server Started")
    s.listen(1)
    while True:
        c, addr = s.accept()
        print("Connection from: " + str(addr))
        filename = ''
        while True:
            data = c.recv(1024).decode('utf-8')
            if not data:
                break
            filename += data
        print("from connected user: " + filename)
        myfile = open(filename, "rb")
        c.send(myfile.read())
        c.close()

if __name__ == '__main__':
    Main()

client.py

#!/usr/bin/env python3 
import socket, os.path, datetime, sys

def Main():
    host = '127.0.0.1'
    port = 50001

    s = socket.socket()
    s.connect((host, port))

    Filename = input("Type in ur file ")
    s.send(Filename.encode('utf-8'))
    s.shutdown(socket.SHUT_WR)
    data = s.recv(1024).decode('utf-8')
    print(data)
    s.close()

if __name__ == '__main__':
    Main()

And now a bit of explanation.

On the server side. The outer loop accepts a connection, then reads from the connection until done (more on this later). Prints your debugging info, but note you were trying to print the file object and not the filename (which would fail trying to concatenate). I also open the file in binary mode (that way I can skip the str -> bytes translation.

On the client side. I've added closing the writing end of the socket when the file has been sent. Note you might want to use sendall instead of send for this use case: check those docs links for details. And I've added a print for the incoming data.

Now that bit with shutting down the writing end in the client and the inner loop reading (and also related to the sendall hint. Which BTW also holds true for the server side, otherwise you should loop, as you might see your content truncated; other option is to also have a sending loop.). Stream sockets will guarantee you get your bytes in in order you've send them. On itself it has no idea whether your message is complete and it also does not guarantee in how many and how large chunks will the data be sent and received (resp.).

The inner loop of server keep reading until we see an EOF (we've receive zero length string in python socket). This would happen (be returned by recv when the remote socket (or at least its writing end) has been shut down. Since we still want to reuse the connection, we only do that on the sending end in the client. Hope this helps you to move ahead.

Ondrej K.
  • 8,841
  • 11
  • 24
  • 39
  • Oh wow. It actually prints the file content right now. Just got a question, by opening the file in binary mode won't it limit the functionality of the file? For example if i open the file in r mode i can do `myfile.readline()` however i can't do that in rb mode. – Crazytech Jul 25 '18 at 13:34
  • When in doubt, check the [docs](https://docs.python.org/3/library/functions.html#open). TL;DR: you can use `readline()`. Apart from the `bytes`/`str` difference and mostly behind the scene details, you should get the same behavior on those higher level interfaces. It's not really all that important, but basically, I see no point of converting data forth and back. So, I'd leave all the conversion to the client for handling console input/output talking to a human. And I got a bit lazy on that too. – Ondrej K. Jul 25 '18 at 14:00
  • Alright. I get your explanation. Thanks alot for your help. Learn quite a few things today. ^^ – Crazytech Jul 25 '18 at 14:15
  • this >> decode('utf-8') it's not bad for binary type of files for example a picture or video ? – Cornea Valentin Oct 02 '21 at 08:27