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?
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)
So I have a program using sockets, it only accept connections, the server.py file listen to a client.py file, but what if I want it to do it that both files can listen and connect.
For example:
here is my server.py
def main():
print("[STARTING] Server is starting...")
""" Starting a TCP socket """
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
server.listen()
print("[LISTENING] Server is listening...")
while True:
""" Accept the connection from the client """
conn, addr = server.accept()
addr = socket.gethostname()
print(f"[NEW CONNECTION] {addr} connected.")
and this is my client.py
def main():
""" Staring a TCP socket. """
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
""" Connecting to the server. """
client.connect(ADDR)
How can I do both of them in only one file like "Server-Client.py".
So if I want to use in one computer Server-Client.py as a client it can be use a a client,
and if I want to use Server-client.py as a server on another computer it can be use as a server and the other way around.
any ideas?
Put the server code in one function and the client code in another function. Then call the appropriate function based on whether the user asked for "client" or "server".
import sys
def client():
# client code here
def server():
# server code here
if __name__ == '__main__':
if sys.argv[1] == 'client':
client()
elif sys.argv[1] == 'server':
server()
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()
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
When creating a TCPServer from the socketserver module, a connection can be made and used continually for communication until one side execute a shutdown command. Having written the following programs, it is unclear to me how to continue communicating with the server if (for various reasons) a UDPServer is required for use. Should the client keep running the sendto and recv methods as needed and pretend that the server will receive the message and return a reply?
Client
import socket
import sys
def main():
host, port = 'localhost', 10000
data = ' '.join(sys.argv[1:])
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(data.encode(), (host, port))
received = client.recv(1 << 12).decode()
print('Sent: ', data)
print('Received:', received)
if __name__ == '__main__':
main()
Server
import socketserver
def main():
host, port = 'localhost', 10000
server = socketserver.UDPServer((host, port), UDPHandler)
server.serve_forever()
class UDPHandler(socketserver.DatagramRequestHandler):
def handle(self):
data = self.rfile.read().strip()
client, port = self.client_address
print(client, 'wrote:', data)
self.wfile.write(data.upper())
if __name__ == '__main__':
main()
Since no guaranteed connection exists when using datagrams, the client may continue sending messages to the server and attempt to receive replies. There is nothing special to do in terms of connecting, shutting down, or closing the socket. The server should use an appropriately written handler as before to receive and send client communications. The following examples demonstrate how to write such programs and include a command-line interface for specifying their parameters.
UDPClient.py
#! /usr/bin/env python3
import argparse
import socket
def main():
parser = argparse.ArgumentParser(description='Execute a UDP client demo.')
parser.add_argument('host', type=str, help='computer where data is sent')
parser.add_argument('port', type=int, help='location where server listens')
arguments = parser.parse_args()
address = arguments.host, arguments.port
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for _ in range(5):
message = input('>>> ').encode('ascii')
client.sendto(message, address)
response = client.recv(1 << 12).decode('ascii')
print(response)
if __name__ == '__main__':
main()
UDPServer.py
#! /usr/bin/env python3
import argparse
import socketserver
def main():
parser = argparse.ArgumentParser(description='Execute a UDP server demo.')
parser.add_argument('port', type=int, help='where the server will listen')
arguments = parser.parse_args()
host = socketserver.socket.gethostbyname(socketserver.socket.gethostname())
address = host, arguments.port
server = socketserver.ThreadingUDPServer(address, ClientRequestHandler)
server.serve_forever()
class ClientRequestHandler(socketserver.DatagramRequestHandler):
def handle(self):
message = self.rfile.read().decode('ascii')
print('Received:', message)
response = 'Received: {}'.format(message).encode('ascii')
self.wfile.write(response)
if __name__ == '__main__':
main()