Bidirectional socket between host and docker container - python

I have seen some similar questions but there don't seem to be answers but if one exists please point me to it. I have boiled down my issue to a self contained example. So all the stuff below is my exact env. I have a docker container that has a python script that listens on a socket and echoes back anything it receives (basically an echo server). The client is running on the host system. I seem to be able to send from the client to the server but the response is never received. I tried some fudging to send the response back to host.docker.internal but it doesn't work. So is this even possible to do? Anyways the details below:
Basically my docker container runs a python script, the Dockerfile looks like this:
FROM python:3.9
ADD main.py .
CMD ["python", "./main.py"]
Then I have docker-compose.yml to create a service with ports forwarding:
version: '3'
services:
web:
image: py-app
ports:
- "8010:8010"
My server (which runs inside the docker container) looks like this:
import socket
DOCKER_HOST = 'host.docker.internal'
HOST = '127.0.0.1'
PORT = 8010
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
while True:
data = conn.recv(1024)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as ds:
ds.connect((DOCKER_HOST, PORT))
ds.sendall(data)
My client that takes input from the keyboard and sends the data to the server running in docker looks like:
import socket
HOST = '127.0.0.1'
DOCKER_PORT = 8010
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, DOCKER_PORT))
print("Connected")
while True:
print("Sending data")
x = input()
x = bytes(x, 'utf-8')
s.sendall(x)
print("Recieving data")
data = s.recv(1024)
print('Received echo: ', repr(data))
There is no error when sending the data into the container but nothing comes out from it. Any thoughts on how I can accomplish what I want to do?

Related

How could we establish connection between server and client through socket programming(Python) with server and client on different networks?

How could we establish connection between server and client through socket programming(Python) with server and client on different devices and on different networks? When we create socket with i/p addr and port
of server, server and client gets connected if both devices are connected on same network. But this is not the case with different networks. What needs to be done to connect them?
import socket
def server_program():
host = socket.gethostname()
port = 5000
server_socket = socket.socket()
server_socket.bind((host, port))
server_socket.listen(2)
conn, address = server_socket.accept()
print("Connection from: " + str(address))
while True:
data = conn.recv(1024).decode()
if not data:
break
print("from connected user: " + str(data))
data = input(' -> ')
conn.send(data.encode())
conn.close()
if __name__ == '__main__':
server_program()
import socket
def client_program():
host = socket.gethostname() // used ngrok i/p here
port = 5000 // used ngrok port no
client_socket = socket.socket()
client_socket.connect((host, port))
message = input(" -> ")
while message.lower().strip() != 'bye':
client_socket.send(message.encode())
data = client_socket.recv(1024).decode()
print('Received from server: ' + data)
message = input(" -> ")
client_socket.close()
if __name__ == '__main__':
client_program()
To establish a connection between server and client on different networks you either need to use port forwarding or you can take help of some external software like ngrok
How do you use ngrok ?
First of all you need to sign up.
Download the ngrok software
Now you would get a screen like this
Copy the line ./ ngrok authtoken .........
Open up cmd and cd into the folder where you've downloaded ngrok
Paste the copied commmand (Note- If you're on windows remove the ./ from starting of the command) and hit enter
Enter the following command
ngrok tcp [Port on which your server is listening]
For example - If your server is listening on port 65432 then you'd have to enter the following command
ngrok tcp 65432
You should now be seeing a window like this
Copy the x.tcp.ngrok...... from the window (highlited in the image above)
Open up cmd and type ping [copied text here]
The output should be something like this :
Pinging x.tcp.ngrok...... [ip here] with 32 bytes of data:
....
....
....
Copy the ip
Now in your client.py file replace the ip with the ip you copied
Copy the port from the ngrok window (Next to the highlighted text in the image above, in my case it's 11171)
Replace the port in client.py file with the port you copied
In server.py change the host to "0.0.0.0"
You're all set to go now! Clients can now connect to your server from all over the globe

How can i connect two computers with python socket?

im new here!
I have a problem with connection between two computers connected with different wi-fi's. After about 20 seconds i get information that connection can't be done.
There is my code:
SERVER:
from socket import *
lista = ['computer']
s = socket(AF_INET, SOCK_STREAM)
port = 21312
s.bind(('my ipv4', port))
s.listen(5)
while True:
for i in range (0, len(lista)):
a = str(lista[i]).encode()
c, addr = s.accept()
print("CONNECTION WITH",addr)
c.send(a)
print(a)
c.close()
CLIENT:
import socket
from socket import *
port = 21312
while True:
s = socket(AF_INET,SOCK_STREAM)
s.connect(('my ipv4', port))
odebrana = (s.recv(1024))
decoded = odebrana.decode()
print(decoded)
s.close()
Likely you are experiencing an issue because your server sits behind a Network Address Translator (NAT). This way your client cannot use the server's IP directly since it is not reachable. There are a few ways around it.
The easiest and not very practical one is: get both machines in the same network, then it should work.
Get a public IP address for the server. You can do that by hosting it on a cloud server that provides you with a public IP, e.g., aws, azure, google cloud etc.
In the old days we used hamachi to get a VPN that would connect both machines. Then they can identify each other over that VPN. Simply turn on hamachi (or any other VPN solution), run your server, then from your client (connected to the VPN), use the VPN's server IP (hamachi will provide you with one when you setup a network).
Disclaimer: I have not used hamachi in about 15 years, but just went through the process because of one of the comments below.
Seems like you can create an account, then once you turn it on you should see your v4 and v6 addresses as shown below:
Highlighted is my v4 address. I suspect you need to create a network, join both PCs in the same network and then use hamachi's IP to emulate behaviour as if they were connected via LAN.
So I faced the similar problem while sending image files between 2 computers using python sockets. I solved the issue by following this way:
First I completed writing the connection code of both server.py and client.py
Note: server.py should be in one computer and client.py should be in another computer.
server.py
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
print(host)
server.bind((host, 12000))
server.listen()
client_socket, client_address = server.accept()
file = open('server_image.jpg','wb')
image_chunk = client_socket.recv(2048)
while image_chunk:
file.write(image_chunk)
image_chunk = client_socket.recv(2048)
file.close()
client_socket.close()
client.py
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET = IP, SOCK_STREAM = TCP
server_host = 'LAPTOP-1231' # Replace this hostname with hostname printed in server.py
client.connect((server_host, 12000)) # 127.0.0.1
file = open('That_Sinking_Feeling_27.jpg', 'rb')
image_data = file.read(2048)
while image_data:
client.send(image_data)
image_data = file.read(2048)
file.close()
client.close()
Now you should add the image in the directory where client.py is located, so that you can send it to another computer (server). Rename it to img.jpg
Then, you need to run server.py in your another computer. It will print the hostname in terminal. Then copy that hostname and paste it in client.py (server_host = hostname_from_server)
Then run client.py
Finally the image will be transferred to new computer (server)

Paramiko server: Redirect the output of a SUBPROCESS to a channel

I am trying to implement a (local fake) server with paramiko that responds to custom commands just like the original for testing purposes. Mainly copying from the supplied demo server, I managed to come up with this custom method to handle exec_requests for the server implemented via paramiko.ServerInterface:
def check_channel_exec_request(self,channel,command):
print("User wants to execute '%s'" %(command))
comm_main, comm_add = command.decode().split(sep=" ",maxsplit=1)
if comm_main in self.allowed_commands:
chout = channel.makefile("w")
subprocess.Popen(command,stdout=chout)
return True
else:
return False
After the server is running via:
PORT = 50007 # The same port as used by the server
HOST = 'localhost'
host_key = paramiko.RSAKey(filename = <FILEPATH>)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((HOST,PORT))
sock.listen(1)
conn, addr = sock.accept() # Connected!
with conn:
trans = paramiko.Transport(conn)
trans.add_server_key(host_key)
trans.set_subsystem_handler("job",JobHandler)
server = FakeCluster() # Custom class sublassing paramiko.ServerInterface
trans.start_server(server=server)
chan = trans.accept() # Accept authentication from client
while trans.is_active(): # Do not close until inactive
time.sleep(1)
chan.close()
the client would try to execute echo 123 in the following manner:
PORT = 50007 # The same port as used by the server
HOST = 'localhost'
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind((HOST,PORT))
ssh = paramiko.client.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, PORT,username=<USERNAME>,password=<PASSWORD>)
ssh.exec_command("echo 123")
Right now, I am getting the error trying to execute the subprocess that 'ChannelFile' has no attribute 'fileno'. Furthermore I am wondering how to later execute a python script as a custom command called by exec_command. (Maybe by calling a batchfile that calls the python script?)
your question is really very confusing , here is what i did for communicating with remote server .
local machine : window
Remote Machine :ubuntu
Command on remote machine :'who'
import paramiko
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.268.21.26',port=22,username='root',password='default')
stdin,stdout,stderr=ssh.exec_command('who')
output=stdout.readlines()
print '\n'.join(output)
#output
#root tty7 2017-11-28 14:13 (:0)
#if you wish to execute a python file there , this should work
stdin,stdout,stderr=ssh.exec_command('python file.py')

Python server client socket

I've tried to connect two computers with a socket in Python and I don't know why it doesn't work. The files are from internet and it compiles for me but without any results.
The server.py:
#!/usr/bin/python
import socket
s = socket.socket()
host = ''
port = 12345
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close()
and the client.py:
#!/usr/bin/python
import socket
s = socket.socket()
host = # here I put the ip of the server's laptop
port = 12345
s.connect((host, port))
print s.recv(1024)
s.close()
What's wrong?
You have to run the server first. Then run the client at the same time with the IP of the server (I used localhost because it was running on one computer, maybe you should try if that works). The code worked fine for me, every time I ran the client, the server printed a message. If it doesn't work for you, maybe your firewall is not letting you open ports.
Just for the future, please always post any error messages you see.
BTW, isn't this the Python Documentation example for sockets?

Cannot run the socket programs correctly in Centos using Python

I'm currently working on with Sockets using Python.
As a starter, I tried copying first the examples given in this (17.2.2. Example) tutorial
I put the client and the server scripts in two different machines (of course)
Now, I want to try if it works, but I'm kind of lost.
I'm thinking of running the server program continuously so that it will keep on receiving the data sent by the client program. However, when I tried to run the Server program, it is giving me this error
socket.error: (99, 'Cannot assign requested address')
and When I tried running the client program, it doesnt give me errors, however, it is printing random data, which is different from what I'm expecting because I sent the String "Hello World", So im expecting that it will receive and print "Hello World"
Shown below is the server program
# Echo server program
import socket
HOST = '192.168.104.112' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
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()
and the one below is the client program
# Echo client program
import socket
HOST = '192.168.104.111' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
Assuming that the IP of the machine that runs the server program is : 192.168.104.111
while the Client program is : 192.168.104.112
Im not really sure where to get the port number so I just used the port showed in the rpyc in the terminal. how do I get the correct port number anyway?
I know I made a lot of mistakes here. I just don't which part. Could you point me the mistakes that i've done and how to correct them? and how do I run these programs?
BTW, i'm using Centos.
On the server, HOST should be either 0.0.0.0 or the server's own IP address. The server needs to bind its listening port to its own interface(s). The client connects to the server.
Your client program doesn't check for errors. So if it can't connect to the server, things go awry.

Categories