How can I create a TCP server using Python 3? - python-3.x

How can I create a TCP server in python3 which will return all the files in the current directory?

You can use the socketserver library, this will serve the current working directory.
Here is the Server code
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
# here you can do self.request.sendall(use the os library and display the ls command)
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
And here is the client side
import socket
import sys
HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])
# Create a socket (SOCK_STREAM means a TCP socket)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
# Connect to server and send data
sock.connect((HOST, PORT))
sock.sendall(bytes(data + "\n", "utf-8"))
# Receive data from the server and shut down
received = str(sock.recv(1024), "utf-8")
print("Sent: {}".format(data))
print("Received: {}".format(received))
You should then get an output like
Server:
127.0.0.1 wrote:
b'hello world with TCP'
127.0.0.1 wrote:
b'python is nice'
Client:
$ python TCPClient.py hello world with TCP
Sent: hello world with TCP
Received: HELLO WORLD WITH TCP
$ python TCPClient.py python is nice
Sent: python is nice
Received: PYTHON IS NICE
You can then just use this code to send the current directory list

You can use socketserver which will serve the current working directory.
import socketserver # import socketserver preinstalled module
import http.server
httpd = socketserver.TCPServer(("127.0.0.1", 9000), http.server.SimpleHTTPRequestHandler)
httpd.serve_forever()

Related

Don't understand why server won't respond to client (even after turning of firewall | Python | Server

I set up my server on MacBook air and my client is connecting from a Windows 10 machine. I turned off all security and firewalls on both machines (because that's what you do when you've lost all hope) and tried to connect from my windows machine multiple times, but to no avail. I'm on the same network btw (not using a VM).
Error:
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Server:
import socket, threading
import multiprocessing
from time import sleep
# tells us the bytes of the message
HEADER = 64
PORT = 5430
# or you could do socket.gethostbyname(socket.gethostname())
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!END'
# defines the type of connection
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def start():
server.listen()
print(f'[LISTENING] Server is listening on {SERVER}')
while True:
conn, addr = server.accept()
print('[ACTIVE CONNECTIONS] 1')
start()
Client:
from time import sleep
import socket, subprocess
HEADER = 64
PORT = 5430
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!END'
SERVER = '192.32.322.3'
ADDR = (SERVER, PORT)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)

How to initiate a socket connection from server to client?

I have setup a tcp socket between a client and a server, very basic. Client side:
#!/usr/bin/env python3
import socket
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = "81.88.95.250"
port = 25000
# connection to hostname on the port.
s.connect((host, port))
# Receive no more than 1024 bytes
msg = s.recv(1024)
s.close()
print (msg.decode('ascii'))
server side:
#!/usr/bin/env python3
import socket
# create a socket object
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
port = 25000
# bind to the port
serversocket.bind((host, port))
# queue up to 5 requests
serversocket.listen(5)
while True:
# establish a connection
clientsocket,addr = serversocket.accept()
print("Got a connection from %s" % str(addr))
msg = 'Thank you for connecting'+ "\r\n"
clientsocket.send(msg.encode('ascii'))
clientsocket.close()
My target is to send notification from client to server, and that's easy. The difficult part is that I also need in some circumstances to start the connection from the server and to send a command to the client and this must be executed as soon as it is received, so I cannot setup a periodic "poll". But I'm quite confused on this part, because the client is behind a NAT, not exposed with a public IP.

OSError: [Errno 22] Invalid argument for udp connection

The udp server and client on my local pc.
cat server.py
import socket
MAX_BYTES =65535
def server():
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind(('127.0.0.1',10000))
print('Listening at {}'.format(sock.getsockname()))
while True:
data,address = sock.recvfrom(MAX_BYTES)
text = data.decode('ascii')
print('The client at {} says {!r} '.format(address,text))
if __name__ == "__main__":
server()
Bind port 10000 with localhost-127.0.0.1,and listening to the message send from client.
cat client.py
import socket
import time
from datetime import datetime
MAX_BYTES =65535
def client():
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind(('127.0.0.1',10001))
text = 'The time is {}'.format(datetime.now())
data = text.encode('ascii')
while True:
time.sleep(10)
sock.sendto(data,('127.0.0.1',10000))
print('The OS assinged me the address {}'.format(sock.getsockname()))
if __name__ == "__main__":
client()
Run the server.py and client.py on my local pc,server can receive message send from client.
Now i change 127.0.0.1 in the line in client.py with my remote vps_ip.
sock.sendto(data,('127.0.0.1',10000))
into
sock.sendto(data,('remote_ip',10000))
Push server.py into my vps.Start client.py on my local pc,server.py on remote vps,start them all.
In my client,an error info occurs:
File "client.py", line 13, in client
sock.sendto(data,('remote_ip',10000))
OSError: [Errno 22] Invalid argument
How to make remote ip receive message send from my local client pc?
Two things that could be happening:
You're not passing the remote IP correctly. Make sure that your not passing literally 'remote_ip' and replace it with a valid IPv4 IP address string (IE: '192.168.0.100') for the server. (FYI technically on the server you can just put '0.0.0.0' to listen on all IP addresses)
You could still be binding the client to the local address to (127.0.0.1), but setting the destination to a valid external address (192.168.0.100). Remove the socket.bind line of code in the client to test this, you shouldn't need it.
If these both don't work, then add the results of a ping command running on the client and targeting the server.

Can't receive an answer from python socket

I have a working command for linux that sends a request and gets a response:
echo -n -e '\x9e\x4c\x23\x00\x00\xff\xff\xce\xf2\x3b\x18\x80' | nc -u -w 1 -p 11244 127.0.0.1 11235
I'm trying to do the same through the python:
import socket
IP = "127.0.0.1"
PORT = 11235
MESSAGE = "9e4c230000ffffcef23b1880"
BINARY_MESSAGE = MESSAGE.decode('hex')
print ("BINARY_MESSAGE: [%s]" % BINARY_MESSAGE) # <- message is the same as echo -en does
srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srvsock.settimeout(3) # 3 seconds
srvsock.connect((IP, PORT))
srvsock.sendall(BINARY_MESSAGE)
data = srvsock.recv(4096)
print ("Received message: [%s]" % data)
srvsock.close()
I receive a blank responce:
BINARY_MESSAGE: [�L#����;�]
Received message: []
I guess I'm doing something wrong.
Your nc command line is using UDP (-u). Your Python code is using TCP (socket.SOCK_STREAM). You want to create a UDP socket:
srvsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
You will want to get rid of the call to connect, but you will need a call bind if you expect to receive messages on that socket. For example, the following code sends a message then waits for a reply on the same socket:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 2222))
s.sendto('this is a test', ('127.0.0.1', 3333))
data, srcaddr = s.recvfrom(1024)
print(data, srcaddr)
Remember that UDP is a connectionless protocol. The other side of this conversation can't "reply" to the message; it needs to explicitly send to the address/port on which the above code is listening. In Python the other side of this conversation might look like:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 3333))
data, srcaddr = s.recvfrom(1024)
print(data)
s.sendto('that was a test', srcaddr)
The above code waits for a message then sends a response back.

python3: two clients sending data to server using sockets

I'm working with 3 raspberry pi, one as a server and the two others are clients. What I want to do is to make the clients communicate with the server simultaneously, I don't want to wait for client1 communication to be done in order to launch client2 request to the server (which I succeeded to do). However, I want each client to send different data to server at the same time. I tried to use Sockets and threading, like below.
server code:
import socket
import RPi.GPIO as GPIO
from threading import Thread
# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print ("[+] New server socket thread started for " + ip + ":" + str(port))
def run(self):
while True :
data = conn.recv(2048)
data = data.decode('utf-8')
print ("Server received data:", data)
MESSAGE = input("Multithreaded Python server : Enter Response from Server/Enter exit:")
if MESSAGE == 'exit':
break
conn.send(str.encode(MESSAGE)) # echo
# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = ''
TCP_PORT = 9050
BUFFER_SIZE = 2000 # Usually 1024, but we need quick response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(2)
threads = []
list_data=[]
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048)
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)
for t in threads:
t.join()
client1 code:
import socket
import RPi.GPIO as GPIO
import time
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient1: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client2 received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
client2 code:
import socket
import RPi.GPIO as GPIO
import time
import socket
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient2: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
when i run, i obtain:
in the server terminal:
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.197:47012
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.196:47886
Multithreaded Python server : Waiting for connections from TCP clients...
in client1 terminal:
tcpClient1: Enter message/ Enter exit:begin
in client2 terminal:
tcpClient2: Enter message/ Enter exit:begin
It seems like server didn't receive or send any data.
As #Hikke mentioned in his comment, your server receives at two different places. The conn.recv call in this code snippet eats up the data that the server receiving thread is expecting. Remove data = conn.recv(2048) in your server's main loop:
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048) # <== dont eat the data of your thread here!
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)

Resources