firstly sorry for my bad english (I'm French) because I'm trying to not use Google Translate.
So, my problem is in the following set of server.py and client.py. Just a client that send every 10 seconds a message with a incremental counter on the server.py. I write this script to check if my university work server "live" or "die" after my logout (and for my training).
server.py:
# -*- coding: utf-8 -*-
import socket
HOST = 'localhost'
PORT = 1602
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(('localhost', PORT))
while True:
socket.listen(5)
client, address = socket.accept()
print(f"{address} connected")
response = client.recv(1024)
print(response.decode())
print("Close")
client.close()
socket.close()
client.py:
# -*- coding: utf-8 -*-
import socket
from apscheduler.schedulers.blocking import BlockingScheduler
HOST = 'localhost'
PORT = 1602
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((HOST, PORT))
print(f"Connection on {PORT}")
timeCount = 0
def some_job():
global timeCount
timeCount += 1
print(f"Send N°{timeCount}")
string = f'Schedule Transmission N°{timeCount}'
socket.send(f"Schedule Transmission N°{timeCount}".encode())
scheduler = BlockingScheduler()
scheduler.add_job(some_job, 'interval', seconds=5)
scheduler.start()
print("Close")
socket.close()
The problem is that the server side print only (and probably receive only) the first message/first transmission. So, not a problem of encodage and the connexion seems to exist even after the first message print.
I understand well the code in itself. I don't see what's the problem. There is any exception or error when running.
Can someone help me, please?
Cordially
I only needed to change your server code. I added multithreading. Now multible clients can connect to the server without blocking the entire process.
# -*- coding: utf-8 -*-
import socket
import threading
HOST = 'localhost'
PORT = 1602
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(('localhost', PORT))
def handle_client(client, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
response = client.recv(1024)
if response:
print(f"[{addr}] {response.decode()}")
client.close()
while True:
socket.listen()
client, addr = socket.accept()
thread = threading.Thread(target=handle_client, args=(client, addr))
thread.start()
Related
I have implemented code for a server and a client using sockets, however I would like the server to send continuously and the client to receive and print the message received until I end either program. The code just prints out once "L2" on the client.
Is it ideal to reverse functionality by receiving with the server and sending with the client?
client.py
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname, 1223))
while True:
msg = s.recv(5)
# clientsocket.close()
print(msg.decode("utf-8"))
server.py
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1223))
s.listen(3)
while True:
clientsocket, address = s.accept()
clientsocket.send(bytes("L2", "utf-8"))
time.sleep(2)
I'm creating a program that uses threads to handle sockets and input at the same time. I've narrowed down the errors I'm getting to be replicable in these couple dozen lines of code. What happens to anyone else who runs the code below? I encounter a hang-up in waiting for the recv in the client. If I further try to send() more data in the server, I get a Broken Pipe error. And, even more weirdly, if I comment out the line that calls input(), the sockets work just fine.
What kind of weird interaction is going on between input(), sockets, and threading? And does anyone have a solution to this? Here's some code that generates the error.
Server:
import socket
import threading
def handle_connection(conn, addr):
data = conn.recv(1024)
message = data.decode('ascii').split()
s = "TEST"
conn.send(bytes(s, 'ascii')) #
conn.close()
def handle_input():
while True:
s = input()
print(s)
HOST = "127.0.0.1" # The server's hostname or IP address
PORT = 2000 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT)); #Empty first string = INADDR_ANY
s.listen();
w = threading.Thread(target=handle_input)
w.start()
while True:
conn, addr = s.accept()
x = threading.Thread(target=handle_connection, args=(conn, addr))
x.start()
s.close()
Client:
import socket
HOST = "127.0.0.1" # The server's hostname or IP address
PORT = 2000 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
message = "find_successor a"
s.connect((HOST, PORT))
s.sendall(bytes(message, 'ascii'))
data = s.recv(1024)
print(f"Received {data!r}")
I appreciate any help or insight!
I'm trying to create a persistent socket connection between a Lua client and Python server. Effectively a script that'll constantly ping the server with keepalive messages
My current issue is that the socket closes after each connection without a means to reopen it for transmission.
Lua Client:
local HOST, PORT = "localhost", 9999
local socket = require('socket')
-- Create the client and initial connection
client, err = socket.connect(HOST, PORT)
client:setoption('keepalive', true)
-- Attempt to ping the server once a second
start = os.time()
while true do
now = os.time()
if os.difftime(now, start) >= 1 then
data = client:send("Hello World")
-- Receive data from the server and print out everything
s, status, partial = client:receive()
print(data, s, status, partial)
start = now
end
end
Python Server:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print("{} wrote".format(self.client_address[0]))
print(self.data)
print(self.client_address)
# Send back some arbitrary data
self.request.sendall(b'1')
if __name__ == '__main__':
HOST, PORT = "localhost", 9999
# Create a socketserver and serve is forever
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
server.serve_forever()
The expected result is a keepalive ping every second to ensure the client is still connected to the server.
I ended up finding a solution.
The problem seems to have been with the socketserver library in Python. I switched it to raw sockets and things began working how I wanted them to. From there I created threads to handle the back and forth in the background
Python Server:
import socket, threading
HOST, PORT = "localhost", 9999
# Ensures the connection is still active
def keepalive(conn, addr):
print("Client connected")
with conn:
conn.settimeout(3)
while True:
try:
data = conn.recv(1024)
if not data: break
message = data.split(b',')
if message[0] == b'ping':
conn.sendall(b'pong' + b'\n')
except Exception as e:
break
print("Client disconnected")
# Listens for connections to the server and starts a new keepalive thread
def listenForConnections():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind((HOST, PORT))
while True:
sock.listen()
conn, addr = sock.accept()
t = threading.Thread(target=keepalive, args=(conn, addr))
t.start()
if __name__ == '__main__':
# Starts up the socket server
SERVER = threading.Thread(target=listenForConnections)
SERVER.start()
# Run whatever code after this
The Lua client didn't change in this scenario
These are my basic Python programs for testing TCP sockets.
server.py:
import socketserver as serv
class Handler(serv.BaseRequestHandler):
def handle(self):
received = self.request.recv(16)
print('received',received)
if __name__ == '__main__':
host, port = 'localhost', 2000
with serv.TCPServer((host,port), Handler) as serv:
serv.allow_reuse_address = True
serv.serve_forever()
client.py:
import socket as Socket
import time
if __name__ == "__main__":
host, port = 'localhost', 2000
with Socket.socket(Socket.AF_INET, Socket.SOCK_STREAM) as socket:
socket.connect((host, port))
socket.send(bytes('1','utf-8')) # First send
time.sleep(0.5)
socket.send(bytes('2','utf-8')) # Second send
The server is run first, followed by client. The server prints:
received b'1'
But I would like it to say this to show that the server received both sends:
received b'1'
received b'2'
Am I missing something that is required between each sends?
How do I get a response from the server?
Client side:
#CLIENT
import socket
import time
host = "localhost"
port = 5454
data_c = input()
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.sendto(bytes(data_c, 'utf-8'),(host,port))
print( data_c )
print( c.recv(1024).decode('utf-8'))
SERVER side:
#SERVER
import socket
import time
host = "localhost"
port = 5454
data_s = "ACKNOWLEDGMENT"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
print(s.recv(1024).decode('utf-8'))
I can send a message from the server that the client will receive, but can not seem to get communication (like an ACK.) to make it back to the server.
(yes UDP is not a good way to be doing this i'm pretty sure, but that was a specific for the project)
for question 1: to send the ACK, you could replicate what you have in the reverse direction.
Since UDP is connection-less you don't know beforehand you receive a packet where the packet will come from, so you have to use recvfrom to get both the packet and the peer (address/port) the packet came from. Then you have to use that address to send data back.
What you're doing now in your client (but what really looks like the server) in the loop is send the same data over and over to itself. Instead in the loop you should receive packets using the previously mentions recvfrom then send replies to the peer you received the packet from.
So something like the following pseudo code
while True:
peer = recvfrom(...)
sendto(..., peer)
After many attempts to get a simple acknowledgment reply from my server this did it.
Beyond literally starting completely over each round, the time.sleep(.1) function was the only missing key. It allowed the server and client both time to close the current socket connection so that there was not an error of trying to bind multiple bodies to a single location or something.
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Working result:
#SERVER
import socket
import time
host = "localhost"
port = 5454
data_s = "ACKNOWLEDGMENT"
while 1:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
received = print("Client: " + s.recv(1024).decode('utf-8')) #waiting to receive
s.close
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
time.sleep(.1)
s.sendto(bytes(data_s, 'utf-8'),(host,port)) #sending acknowledgment
print("Server: " + data_s)
s.close # close out so that nothing sketchy happens
time.sleep(.1) # the delay keeps the binding from happening to quickly
Server Command Window:
>>>
Client: hello
Server: ACKNOWLEDGMENT
Client:
#CLIENT
import socket
import time
host = "localhost"
port = 5454
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while 1:
data_c = input("Client: ")
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.sendto(bytes(data_c, 'utf-8'),(host,port)) #send message
c.close
# time.sleep()
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.bind((host, port))
print("Server: " + c.recv(1024).decode('utf-8')) # waiting for acknowledgment
c.close
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
time.sleep(.1)
Client Command Window:
>>>
Client: hello
Client: hello
Server: ACKNOWLEDGMENT
I did finally remove the redundant input("Client: ") there at the top.
A special thanks #JoachimPileborg for helping, but I have to give it to the little guy just because it was the path I ended up taking.