Python socket + daemon stopped after sending data - python

I am writing python daemon, which waiting for request and return the some data. But, when request the script by client, the daemon stopped it's work.
This is the code
......
def run(self):
while True:
server_socket = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
server_socket .bind((host, port)) # Bind to the port
server_socket .listen(5)
client_socket, address = server_socket.accept()
# Establish connection with client.
print 'Got connection from', address
logging.info(address)
#data = client_socket.recv(2048)
data = client_socket.recv(1024)
logging.info(data)
......

I am not certain what you really want to be the server functionality, but based on your example, what you have is a server that can accept and process one client at a time. What I would suggest is not rebinding the server every time after every connection. It is not necessary.
Bind the socket once, then go into a loop waiting for clients:
def run(self):
server_socket = socket.socket()
host = socket.gethostname()
port = 12345
server_socket.bind((host, port))
server_socket.listen(5)
while True:
# this will block until a client tries to connect
client_socket, address = server_socket.accept()
print 'Got connection from', address
logging.info(address)
# this will block until data is received from client
data = client_socket.recv(1024)
logging.info(data)
What will happen here is the server will accept a client and then block while waiting for the client to send something. Then it will loop again waiting for a new client. You may even want to close that socket if it is a one-off connection and you are done handling it.
If you want to be able to handle multiple clients at the same time, then you would do the loop in your main thread, and then pass each new connection off to a worker thread to handle the communication. This will free up the main thread to continue looping and waiting for new clients to connect.
This can be achieved by either starting a brand new thread for each client and passing the socket, or, using a Queue shared between a fixed pool of running threads. Each thread would be waiting to pull an item from the queue, and then go into a communication loop on the socket item. When it is done, it goes back to waiting on the queue.
Pseudo-code might look something like this:
socket_queue = Queue()
...
def main_server_thread():
while True:
# this will block until a client tries to connect
client_socket, address = server_socket.accept()
print 'Got connection from', address
logging.info(address)
# this will finish right away and loop again
socket_queue.put(client_socket)
...
def client_worker_thread():
while True:
sock = socket_queue.get()
while sock is still connected:
data = sock.recv(1024)
logging.info(data)

Related

server-client where the client listens and responds in a loop doesn't work (python)

I'm building a Client-Server connection for an assignment. The server basically runs everything and the client only receives messages from the server and responds when the server needs it to.
For some reason, I can't build a client that repeatedly listens and then responds.
I thought that I could just listen with socket.recv() and it ended up just stopping everything.
this is what I ended up with after some tweaking (for the client) :
import socket
HOST = 'localhost'
PORT = 65432
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((HOST, PORT))
conn.setblocking(False)
while True :
try :
msg_lgn = len(conn.recv(1024,socket.MSG_PEEK))
server_message = conn.recv(1024).decode()
print('Server Sent:\n' + server_message)
if server_message == 'exit':
break
except :
conn.send(input().encode())
conn.close()
I set it to non-blocking so it won't hang on the conn.recv() and move on to input in the exception, but then it just freezes on the input.
does the server close the connection every time recv() gets nothing ? why is this happening ?
I just want the client to receive messages whenever the server sends them, and when the server doesn't send, the client will send the server it's input.
would appreciate any help!
Lidor
Edit : the server file is much bigger, so i'll show the important parts.
#imported some classes for the game itself also (that i've created), but has nothing to do with the problem
import socket
import time
import threading
def startGame(conn):
#this is where the servers sends the questions and receives answer (pretty basic send and recv)
# Establish Client-Server Connection
HOST = 'localhost' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(3)
# Use Threading to start the game for an new player
while True:
if playerCount < 3:
(conn, addr) = s.accept()
playerCount += 1
x = threading.Thread(target=startGame, args=(conn,))
x.start()
# Close Server Socket
s.close()

How to fix multiprocessing echo server to handle multiple clients

I want to create a multiprocessing echo server. I am currently using telnet as my client to send messages to my echo server.Currently I can handle one telnet request and it echos the response. I initially, thought I should intialize the pid whenever I create a socket. Is that correct?
How do I allow several clients to connect to my server using multiprocessing.
#!/usr/bin/env python
import socket
import os
from multiprocessing import Process
def create_socket():
# Create socket
sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Port for socket and Host
PORT = 8002
HOST = 'localhost'
# bind the socket to host and port
sockfd.bind((HOST, PORT))
# become a server socket
sockfd.listen(5)
start_socket(sockfd)
def start_socket(sockfd):
while True:
# Establish and accept connections woth client
(clientsocket, address) = sockfd.accept()
# Get the process id.
process_id = os.getpid()
print("Process id:", process_id)
print("Got connection from", address)
# Recieve message from the client
message = clientsocket.recv(2024)
print("Server received: " + message.decode('utf-8'))
reply = ("Server output: " + message.decode('utf-8'))
if not message:
print("Client has been disconnected.....")
break
# Display messags.
clientsocket.sendall(str.encode(reply))
# Close the connection with the client
clientsocket.close()
if __name__ == '__main__':
process = Process(target = create_socket)
process.start()
It's probably a good idea to understand which are blocking system calls and which are not. listen for example is not blocking and accept is blocking one. So basically - you created one process through Process(..), that blocks at the accept and when a connection is made - handles that connection.
Your code should have a structure - something like following (pseudo code)
def handle_connection(accepted_socket):
# do whatever you want with the socket
pass
def server():
# Create socket and listen to it.
sock = socket.socket(....)
sock.bind((HOST, PORT))
sock.listen(5)
while True:
new_client = sock.accept() # blocks here.
# unblocked
client_process = Process(target=handle_connection, args=(new_client))
client_process.start()
I must also mention, while this is a good way to just understand how things can be done, it is not a good idea to start a new process for every connection.
The initial part of setting up the server, binding, listening etc (your create_socket) should be in the master process.
Once you accept and get a socket, you should spawn off a separate process to take care of that connection. In other words, your start_socket should be spawned off in a separate process and should loop forever.

How to send and receive from the same socket in Python?

I'm am trying to write a client program in Python that can send and receive from the same socket, but it is always giving me the same error which address is already in use. Here is the function I'm trying to write.
def Login():
username=raw_input()
password=raw_input()
message=raw_input()
array=[username,password,message]
TCP_IP = '127.0.0.1'
TCP_PORT = 5563
BUFFER_SIZE = 1024 # Normally 1024, but we want fast response
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((TCP_IP, TCP_PORT))
array_string=pickle.dumps(array)
sock.send(array_string)
sock.close()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((TCP_IP, TCP_PORT))
sock.listen(1)
conn, info = sock.accept()
while 1:
data = serverSocket.recv(1024)
if not data:break
conn.send(data)
conn.close()
There is a bunch of truly newbie errors here.
You can't ever connect a TCP socket to itself. There must be two different sockets.
If you really want to get the data you sent earlier at a listening socket, this listening socket must be created, bound and configured to listen before the client side connects (or, at least, in parallel to this connect attempt, in a few seconds, so the connect attempt will try - but this very likely won't work on localhost).
You can't wait on connect and on accept in the same thread if both are blocking. The simplest approach is to separate the client side and the server side to 2 different programs and run them manually in parallel. Then, after successful debugging, you will be able to do this in different threads of the same process, or using an event-driven engine.
While you may not be able to connect a socket to itself to send and receive data, you might be able to learn from the following example inspired by your code that attempts to do something similar.
import _thread
import pickle
import socket
import time
def main():
"""Run a server in a thread and start a client to talk to it."""
_thread.start_new_thread(run_server, ('', 5563))
run_client('localhost', 5563)
def run_server(host, port):
"""Handle all incoming connections by spawning worker threads."""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(5)
while True:
_thread.start_new_thread(handle_connection, server.accept())
def handle_connection(client, address):
"""Answer an incoming question from the connected client."""
print('Incoming connection from', address)
client.settimeout(0.1)
data = recvall(client)
client.shutdown(socket.SHUT_RD)
question = pickle.loads(data)
answer = '''len(username) = {}
len(password) = {}
len(message) = {}'''.format(*map(len, question))
client.sendall(answer.encode())
client.shutdown(socket.SHUT_WR)
client.close()
print('Finished with', address)
def recvall(connection):
"""Receive all data from a socket and return as a bytes object."""
buffer = bytearray()
while True:
try:
data = connection.recv(1 << 12)
except socket.timeout:
pass
else:
if data:
buffer.extend(data)
else:
return bytes(buffer)
def run_client(host, port):
"""Collect information from question and display returned answer."""
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
time.sleep(0.1) # wait for server to start listening for clients
client.connect((host, port))
time.sleep(0.1) # wait for handler thread to display connection
username = input('Username: ')
password = input('Password: ')
message = input('Message: ')
question = pickle.dumps((username, password, message))
client.sendall(question)
client.shutdown(socket.SHUT_WR)
answer = recvall(client)
client.shutdown(socket.SHUT_RD)
client.close()
print(answer.decode())
time.sleep(0.1) # wait for handler to cleanly terminate execution
if __name__ == '__main__':
main()

Python TCP several listen on several ports at once

I'm building a python server that basically has a bunch of ports listening for connections. when a connection is made, the port spits out a message, closes the connection and , resets (ie waits for the next connection).
desired function:
create TCP socket for each port in portlist (this is dynamically populated via arguments)
listen for connection
when a connection made, send message, and disconnect
continue to listen
I have a feeling that my answer may ly in multi threading, but I'm not sure...My code so far:
for port in portlist:
ds = ("0.0.0.0", port)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(ds)
server.listen(1)
while 1:
connection, address = server.accept()
message="message\n"
connection.send(message)
connection.close()
There is single-threaded approach (on the listening side anyway - actually handling the connections may still require multiple threads).
You should open all of your sockets up-front, and put them in a list.
Then, you should select on all of them, which will return when any one of them is ready to be accepted on.
Something like this (totally untested):
servers = []
for port in portlist:
ds = ("0.0.0.0", port)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(ds)
server.listen(1)
servers.append(server)
while True:
# Wait for any of the listening servers to get a client
# connection attempt
readable,_,_ = select.select(servers, [], [])
ready_server = readable[0]
connection, address = ready_server.accept()
# Might want to spawn thread here to handle connection,
# if it is long-lived

Passing _socketobjects as parameters

I'm writing a multithreaded distributed networking algorithm.
I've one thread that listens to new connections. Every time a new connection is established a separate thread is started for listening to messages from that connection.
My problem is that the socket I open works perfectly in both directions inside the connection listener. After I pass the socket object for that connection to the message listener I can read data from the socket, but sending data through it doesn't reach the remote host.
Here's the essential snip from my code:
def connection_listener(port, start_e, terminate_e):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.settimeout(1)
s.bind(('', port))
s.listen(1)
while (not start_e.isSet()):
try:
conn, addr = s.accept()
msg_in = conn.recv(1024).split(":")
if (msg_in[1]=="hello"):
# If addr sends us a 'id:hello', we reply with a 'my_id:welcome'
conn.send(str(my_id)+":welcome")
t = Thread(target=message_listener, args=(conn, addr[0], terminate_e, ))
t.start()
except:
pass # timeout
def message_listener(conn, address, terminate_e):
while (not terminate_e.isSet()):
try:
msg_in = conn.recv(1024)
# Here I can receive everything that I send from the other end of conn,
# but conn.send("any data") doesn't reach the remote host
What I'd like to do is send acknowledgement-like messages from the message listener thread using the conn. Is this possible somehow or am I thinking and doing it wrong?
I sorted this out myself, so I'll share my answer.
I made the protocol exchange fixed size messages by padding with zeroes up to the desired length. I used a length of 32 bytes, which might be quite tiny from the hardware's point of view. Nevertheless it seems to work as supposed.
Pragmatically my solution looks like:
def send_everyone(message):
for i in range(len(peers)):
chunk = (str(my_id)+":"+message).rjust(32, '0')
peers[i].send(chunk)
And on the receiving side we want only 32 bytes at a time:
def message_listener(conn, address, terminate_e):
while (not terminate_e.isSet()):
try:
msg_in = conn.recv(32)
...

Categories

Resources