Why Python Socket works only on local network? - python

I'm trying to send a text file trhough Python sockets and it works but only on local network. Why is that?(I'm working with Python 3.6)
This is the server.py:
import socket
HOST = '0.0.0.0'
PORT = 80
ADDR = (HOST,PORT)
BUFSIZE = 4096
print(socket.gethostbyname(socket.gethostname()))
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv.bind(ADDR)
serv.listen(5)
print ('listening ...')
while True:
conn, addr = serv.accept()
print ('client connected ... ', addr)
myfile = open('asd.txt', 'w')
while True:
data = conn.recv(BUFSIZE)
if not data: break
myfile.write(data.decode("utf-8"))
print ('writing file ....')
myfile.close()
print ('finished writing file')
conn.close()
print ('client disconnected')
This is the client.py:
import socket
HOST = '192.168.2.109'
PORT = 80
ADDR = (HOST,PORT)
BUFSIZE = 4096
textfile = "C:/Users/Public/asd.txt"
bytes = open(textfile, "r").read()
print (len(bytes))
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect_ex(ADDR)
client.send(bytes.encode())
client.close()
I've tried this and it worked on local network, but when I sent to my friend the client to try it, it just printed out the bytes but didn't connect to my server.(The server was running on my pc)

If the client and host are connected to the same network(LAN) i.e through same router or a hotspot, then the above code will work. If you want to do something like, run server.py on a PC connected to your WiFi and run client.py on a laptop connected through dongle you will have to use port-forwarding.

Related

How to make multithread socket on different vms

I want to implement multithreaded-server receives connection from multiple clients on different VMs. 3 VMs are in the same subnet. I would ask how to make it can connect to each other by configuring the network on vms and how to change ip and port in code. Here is the code on server:
import socket
from threading import Thread
from SocketServer import ThreadingMixIn
TCP_IP = 'localhost'
TCP_PORT = 12345
BUFFER_SIZE = 1024
class ClientThread(Thread):
def __init__(self,ip,port,sock):
Thread.__init__(self)
self.ip = ip
self.port = port
self.sock = sock
print " New thread started for "+ip+":"+str(port)
def run(self):
filename='mytext.txt'
f = open(filename,'rb')
while True:
l = f.read(BUFFER_SIZE)
while (l):
self.sock.send(l)
l = f.read(BUFFER_SIZE)
if not l:
f.close()
self.sock.close()
break
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpsock.listen(5)
print "Waiting for incoming connections..."
(conn, (ip,port)) = tcpsock.accept()
print 'Got connection from ', (ip,port)
newthread = ClientThread(ip,port,conn)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
Client1:
import socket
TCP_IP = 'localhost'
TCP_PORT = 12345
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
with open('received_file', 'wb') as f:
print 'file opened'
while True:
data = s.recv(BUFFER_SIZE)
print('data=%s', (data))
if not data:
f.close()
print 'file close()'
break
f.write(data)
s.close()
print('connection closed')
Client2:
import socket
TCP_IP = 'localhost'
TCP_PORT = 12345
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
with open('received_file', 'wb') as f:
print 'file opened'
while True:
data = s.recv(BUFFER_SIZE)
print('data=%s', (data))
if not data:
f.close()
print 'file close()'
break
f.write(data)
s.close()
print('connection closed')
When you are binding to "localhost" IP address it means that your server starts listening on "loopback" internal virtual networking interface with address 127.0.0.1 which can be accessed from local machine but not from outside.
Your server does not listen on any physical interfaces which look into world so even properly configured clients would not be able to connect to your server from remote nodes.
You can replace "localhost" with "0.0.0.0" - which means "bind to all available interfaces".
This means that you can start your server without knowledge of IP address(es) of your own server.
It will be waiting incoming connections on all physical and virtual interfaces which are configured in your VM.
TCP_IP = '0.0.0.0'
tcpsock.bind((TCP_IP, TCP_PORT))
But clients need to know IP address of your server to be able to connect to it.
Right now your clients try to connect to theirs own VM by using IP address 127.0.0.1
You need to provide clients with real IP address of your server for them to connect to it.
Lets assume that your server has address 192.168.4.4
Then your client code should look this way:
TCP_IP = '192.168.4.4'
s.connect((TCP_IP, TCP_PORT))

TCP client server not receiving any data from each other

I have written the following TCP client and server using python socket module. However, after I run them, no output is being given. It seems that
the program is not able to come out of the while loop in the recv_all method
Server:
import socket
def recv_all(sock):
data = []
while True:
dat = sock.recv(18)
if not dat:
break
data.append(dat)
return "".join(data)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '127.0.0.1'
PORT = 45678
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((HOST, PORT))
sock.listen(1)
print "listening at", sock.getsockname()
while True:
s, addr = sock.accept()
print "receiving from", addr
final = recv_all(s)
print "the client sent", final
s.sendall("hello client")
s.close()
Client :
import socket
def recv_all(sock):
data=[]
while True:
dat=sock.recv(18)
if not dat:
break
data.append(dat)
return "".join(data)
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
PORT=45678
HOST='127.0.0.1'
sock.connect((HOST,PORT))
sock.sendall("hi server")
final=recv_all(sock)
print "the server sent",final
Because in server file you use an endless loop in another. I suggest you to edit recv_all method in both files this way:
def recv_all(sock):
data = []
dat = sock.recv(18)
data.append(dat)
return "".join(data)
But after edit like this your server stays on until KeyInterrupt, while you should run client file everytime you want to send data. If you want an automatically send/receive between server and client, I offer you try threading.

How to download file from local server in Python

Scenario is:
Client will Enter a file name e.g xyz
Server will show all the files that it have in different folders.
Client will select 1 or 2 or 3 (if there).
and file will be downloaded.
I have done searching part. I want help in downloading and saving the file in any other directory.
My code so far is for searching the file.
import socket
tcp_ip="127.0.0.1"
tcp_port=1024
buffer_size= 200
filename=raw_input("Enter file name\n")
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((tcp_ip,tcp_port))
data=s.recv(buffer_size)
s.close()
Server Code : (This code is now for one file) The required help is how to download and save that file which is found at server.
import socket
import os
tcp_ip='127.0.0.1'
tcp_port=1024
buffer_size=100
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((tcp_ip, tcp_port))
s.listen(1)
conn, addr = s.accept()
print 'Connection Address:',addr
while 1:
data=conn.recv(buffer_size)
if not data:
break
else:
print "received server side data:", data
conn.send(data)
conn.close()
Following is the example which shows how to download a file from a server over tcp.
Client Code:
import socket
import os
HOST = 'localhost'
PORT = 1024
downloadDir = "/tmp"
filename = raw_input('Enter your filename: ')
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(filename)
with open(os.path.join(downloadDir, filename), 'wb') as file_to_write:
while True:
data = socket1.recv(1024)
if not data:
break
file_to_write.write(data)
file_to_write.close()
socket1.close()
Server Code:
import socket
HOST = 'localhost'
PORT = 1024
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((HOST, PORT))
socket.listen(1)
while (1):
conn, addr = socket.accept()
reqFile = conn.recv(1024)
with open(reqFile, 'rb') as file_to_send:
for data in file_to_send:
conn.sendall(data)
conn.close()
socket.close()
Note: server code is not robust and will crash when file doesn't exists. You should modify above example according to your needs.

client-server chat python error

I'm trying the following client and server chat program. Although I get an error whenever I try to run the server program, when the client program runs it stays on a blank screen not allowing me to type anything. I've tried running server first and running client first and I get the same results. I can't read the error from the server program because it flashes the error and closes the window. Here is my code:
server:
#server
import socket
import time
HOST = ''
PORT = 8065
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((HOST,PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
client:
#client
import socket
import time
HOST = "localhost"
PORT = 8065
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((HOST,PORT))
s.sendall('Helloworld')
data = s.recv(1024)
s.close()
print 'Recieved', repr(data)
Im not an expert but I was able to make your examples work by changing the socket from datagram to stream connection, and then encoding message being sent because strings aren't supported (although this might not effect you since I think that change was made in Python 3...I'm not 100% sure).
I believe the main issue is that you're trying to listen() but SOCK_DGRAM (UDP) doesn't support listen(), you just bind and go from there, whereas SOCK_STREAM (TCP) uses connections.
If you're just trying to get the program going, use the below code, unless there is a specific reason you'd like to use SOCK_DGRAM.
The code is below:
client
#client
import socket
import time
HOST = "localhost"
PORT = 8065
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
test = 'Helloworld'
s.sendall(test.encode())
data = s.recv(1024)
s.close()
print 'Recieved', repr(data)
server
#server
import socket
import time
HOST = ''
PORT = 8065
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST,PORT))
s.listen(1)
conn, addr = s.accept()
print ('Connected by', addr)
while 1:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()

Python - Server and client problems

I'm trying to create a basic server and client script. The idea is that the client can connect to the server and execute commands. Kinda like SSH but very simple. Heres my server code:
import sys, os, socket
host = ''
port = 50103
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("Server started on port: ", port)
s.listen(1)
while (1):
conn, addr = s.accept()
print 'New connection from ', addr
try:
while True:
rc = conn.recv(2)
pipe = os.popen(rc)
rl = pipe.readlines()
fl = conn.makefile('w', 0)
fl.writelines(rl[:-1])
fl.close()
except IOError:
conn.close()
And here is my client:
import sys, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = 'localhost'
port = input('Port: ')
s.connect((host, port))
while (1):
cmd = raw_input('$ ')
s.send(cmd)
file = s.makefile('r', 0)
sys.stdout.writelines(file.readlines())
file.close()
Here is my problem. I start the server and then run the client on the same machine. I enter the port and connect. Then I get the raw_input which is the '$'. If I type a command like 'ls' it just hangs on the client side. I have to exit the server for the client to receive the output of ls. By the way I am running Ubuntu Linux. Not sure if that matters.
When you makefile() on the socket and then use readlines() on it, it will continue until you reach an end of file, which in the socket case is that it closed from the other end.
Using makefile() in this case makes no sense to me, especially since you create it and close it after each command. Just use send() and recv() on both ends.
You probably also want to have some sort of actual "protocol" so the server tells the client "HERE COMES A RESPONSE" and "THIS IS THE END OF THE RESPONSE" so that the client knows. Otherwise it gets hard to know when to stop waiting for more response. :)
Update with an example that works:
server.py:
import sys, os, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 50500))
print("Server started")
s.listen(1)
while True:
print "Accepting"
conn, addr = s.accept()
print 'New connection from ', addr
while True:
try:
rc = conn.recv(1024)
print "Command", rc
if not rc.strip():
continue
if rc.strip() == 'END':
print "Close"
conn.send("**END**")
conn.close()
break
else:
conn.send("This is the result of command %s\n" % rc)
except Exception:
conn.close()
sys.exit()
client.py
import sys, os, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 50500))
while True:
cmd = raw_input('$ ')
s.send(cmd)
result = s.recv(1024)
print result
if result == "**END**":
print "Ending"
break
Well for one thing you're only connecting on the client once and on the server you're closing the socket after every read.
You should take a look at this example.
http://ilab.cs.byu.edu/python/socket/echoserver.html
You're doing quite a few things incorrectly.

Categories