Send data between two python Scripts in continous succession - python

I basically want to send data from one python file to the other, then have the other python file send some more data back to the first file, and then the first file send data again, and this goes on until I choose to stop sending data.
server.py:
import socket
s = socket.socket()
host = "127.0.0.1"
port = 5409
s.bind((host, port))
s.listen(1)
while True:
c, addr = s.accept()
print 'Got connection from', addr
while True:
message = raw_input(">>")
s.sendall(message)
try:
print s.recv(1024)
except:
print ""
client.py:
import socket
s = socket.socket()
host = "127.0.0.1"
port = 5409
s.connect((host, port))
while True:
print s.recv(1024)
message = raw_input(">>")
s.send(message)
I have been trying for a while and I have found nothing online other than a server and client that send data once between them and then close the connection. What can I do?

in server.py
replace s.sendall(message) and s.recv(1024) with c.sendall(message) and s.recv(1024).

I recommend you to try zmq library. Great one for this kind of stuff.
Start server, then start client server will stay open until you send trough client to close server. Hope it helps!
More about zmq you can see here
Server listener
import time
import zmq
import json
from datetime import datetime
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:50165")
import re
while True:
# Wait for next request from client
message = socket.recv()
message = str(message)
print(datetime.now(),message)
# Send reply back to client
socket.send(b"Data Recieved")
Client
import zmq
from time import sleep
context = zmq.Context()
# Socket to talk to server
print("Connecting to hello world server…")
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:50165")
sleep(2)
# Do 10 requests, waiting each time for a response
for request in range(10):
print("Sending request %s …" % request)
socket.send(b"1Hello")
sleep(0.01)
# Get the reply.
message = socket.recv()
print("Received reply %s [ %s ]" % (request, message))

Related

Python console chat with socket

I'm writing a simple console chat with server and client. When receiving a message from the first client server should send it to the second client and vice versa. But when first client sends a message to the server it returns back and doesn't reach the second client. Maybe there is a problem in receiving() function.
Here is my client.py:
import socket
from _thread import *
def recieving(clientSocket):
while True:
encodedMsg = clientSocket.recv(1024)
decodedMsg = encodedMsg.decode('utf-8')
print(decodedMsg)
def chat(clientSocket, name):
msg = input()
encoded_msg = f'[{name}] {msg}'.encode('utf-8')
clientSocket.send(encoded_msg)
def main():
serverAddress = (socket.gethostname(), 4444)
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect(serverAddress)
name = input('Enter your name: ')
start_new_thread(recieving, (clientSocket,))
while True:
chat(clientSocket, name)
if __name__ == "__main__":
main()
And server.py:
import time
import socket
from _thread import *
def listen(clientSocket, addr):
while True:
encodedMsg = clientSocket.recv(1024)
decodedMsg = encodedMsg.decode('utf-8')
currTime = time.strftime("%Y-%m-%d-%H.%M.%S", time.localtime())
for client in clients:
if addr != client:
clientSocket.sendto(encodedMsg, client)
print(f'[{currTime}] {decodedMsg}')
def main():
serverAddress = (socket.gethostname(), 4444)
global clients
clients = []
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.bind(serverAddress)
serverSocket.listen(2)
while True:
clientSocket, addr = serverSocket.accept()
if addr not in clients:
clients.append(addr)
print(f'{addr} joined chat')
start_new_thread(listen, (clientSocket, addr))
if __name__ == '__main__':
main()
sendto doesn't work as expected if its socket is connected. It just sends to the connected socket, not the specified address.
Therefore, listen needs to be able to access the open socket of each client in order to write to it.
Currently clients is a list of addresses, but you could change it to a dict of address to socket mappings:
def main():
global clients
clients = {}
Then when you get a new client connection, save address and socket:
clientSocket, addr = serverSocket.accept()
if addr not in clients:
clients[addr] = clientSocket
print(f'{addr} joined chat')
start_new_thread(listen, (clientSocket, addr))
Finally, in listen, write to each other client's socket, not the connected clientSocket for that listen thread:
for client in clients:
if addr != client:
print(f"sending message from {addr} to {client}")
clients[client].send(encodedMsg)
There's a number of other problems with your code.
Sockets are not thread safe. So there is a race condition if 2 clients happen to write the same thing at the same time; the writes could be interpolated and the messages munged up.
If a client disconnects, the server doesn't handle the disconnection well. If the server disconnects, the clients go into an infinite loop as well.

Connection between client and server fails, send/recv doesnt work (python)

I have put together a server and client code to use in a messaging app. When I run the server and starts one client, everything works fine. When I start a second client, I can send messages from the first client and the second client will recieve them. I can send one message from the second client and the first client will recieve this first message. But after this message, the second client can not send or the server can not receive the data for some reason. The first client can still send messages.
I dont know where the mistake is, but I believe either the client can not .send() or the server can not .recv().
(I am quite new to programming so the code might be quite messy and not the most understandeble, and maybe there are several flaws...)
The server code
import socket
from _thread import *
import sys
HOST = "127.0.0.1"
PORT = 12000
client_socket = set()
def threaded(conn):
while True:
try:
data = conn.recv(1024).decode()
if not data:
print("Lost connection")
break
for conn in client_socket :
conn.send(data.encode())
except:
break
print("Gone")
conn.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
print("Server is up and running")
while True:
conn, addr = s.accept()
print("Connected to", addr)
client_socket .add(conn)
start_new_thread(threaded, (conn, ))
The client code
import threading
import socket, sys
HOST = "127.0.0.1"
PORT = 12000
check= ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
def background():
while True:
answer= s.recv(1024).decode()
if check!= answer and answer!= "":
print(answer)
threading1 = threading.Thread(target=background)
threading1.daemon = True
threading1.start()
while True:
message= input()
if message!= "":
s.send(message.encode())
check = message

Simple Python 3 Chat; Sending and receiving at the same time

I am a total beginner in Python and today I tried to create a simple chat-program. So far it doesn't work too bad, but I am unable to communicate between the server and the client. I can only send from the server to the client but not in the other direction. I tried it with multithreading and these are the results:
Server:
import socket
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "127.0.0.1"
port = 4444
s.bind((host, port))
s.listen(3)
conn, addr = s.accept()
print("Connection from: "+str(addr[0])+":"+str(addr[1]))
def recv_data():
while True:
data = s.recv(2048).decode('utf-8')
print(data)
def send_data():
while True:
msg = input(str(socket.gethostname())+"> ")
msg = str(host + "> ").encode('utf-8') + msg.encode('utf-8')
conn.send(msg)
#t1 = threading.Thread(target=recv_data)
t2 = threading.Thread(target=send_data)
#t1.start()
t2.start()
Client:
import socket
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "127.0.0.1"
port = 4444
s.connect((host, port))
print("Connected to: "+ host)
def recv_data():
while True:
data = s.recv(2048)
data = data.decode('utf-8')
print(data)
def send_data():
while True:
msg = input(str(host)+"> ").encode('utf-8')
s.send(msg)
t1 = threading.Thread(target=recv_data)
#t2 = threading.Thread(target=send_data)
t1.start()
#t2.start()
This code works; the server can send, the client receive, but whenever I uncomment the second thread, so that it can do both I get an error:
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
I can't seem to find a solution, so please help, what am I doing wrong? :D
conn, addr = s.accept()
def recv_data():
while True:
data = s.recv(2048).decode('utf-8')
print(data)
conn is actually the socket you want to send or recv. The error occurs because you are trying to recv from the server socket, which is illegal action. Therefore you need to change s to conn if you want to make it work.

UDP Client/Server Socket in Python

I'm new to python and sockets and am trying to write an echoing client/server socket. I have written the server so that 30% of the packets are lost. I programmed my client to timeout after one second since the packet could be lost. However, whenever I run my client socket, my output is 100% REQUEST TIMED OUT. I'm assuming I'm getting this output because my server is never receiving the message. I've looked over my code multiple times and cannot figure out why I am constantly getting this output. Below is my code for my server and client sockets. Any help would be appreciated.
Server Socket:
# We will need the following module to generate randomized lost packets
import random
from socket import *
# Create a UDP socket
# Notice the use of SOCK_DGRAM for UDP packets
serverSocket = socket(AF_INET, SOCK_DGRAM)
# Assign IP address and port number to socket
serverSocket.bind(('', 12000))
while True:
# Generate random number in the range of 0 to 10
rand = random.randint(0, 10)
# Receive the client packet along with the address it is coming from
message, address = serverSocket.recvfrom(1024)
# Capitalize the message from the client
message = message.upper()
# If rand is less is than 4, we consider the packet lost and do notrespond
if rand < 4:
continue
# Otherwise, the server responds
serverSocket.sendto(message, address)
Client Socket:
import time
from socket import *
pings = 1
#Send ping 10 times
while pings < 11:
#Create a UDP socket
clientSocket = socket(AF_INET, SOCK_DGRAM)
#Set a timeout value of 1 second
clientSocket.settimeout(1)
#Ping to server
message = 'test'
addr = ("127.0.0.1", 12000)
#Send ping
start = time.time()
clientSocket.sendto(message, addr)
#If data is received back from server, print
try:
data, server = clientSocket.recvfrom(1024)
end = time.time()
elapsed = end - start
print data + " " + pings + " "+ elapsed
#If data is not received back from server, print it has timed out
except timeout:
print 'REQUEST TIMED OUT'
pings = pings - 1
I tested your code, and it works as expected on my machine. Your issue might not be your code. It could be a firewall or something else blocking all the packets on the loopback interface (127.0.0.1). Depending on your operating system, try testing with a packet monitor like Wireshark.
Also, here are a few suggestions on how to improve your code to be more Pythonic:
Server
import random
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('', 12000))
while True:
rand = random.randint(0, 10)
message, address = server_socket.recvfrom(1024)
message = message.upper()
if rand >= 4:
server_socket.sendto(message, address)
Client
import time
import socket
for pings in range(10):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.settimeout(1.0)
message = b'test'
addr = ("127.0.0.1", 12000)
start = time.time()
client_socket.sendto(message, addr)
try:
data, server = client_socket.recvfrom(1024)
end = time.time()
elapsed = end - start
print(f'{data} {pings} {elapsed}')
except socket.timeout:
print('REQUEST TIMED OUT')
Here is an alternative with asyncio.
import asyncio
import random
class EchoServerProtocol:
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
message = data.decode()
print('Received %r from %s' % (message, addr))
rand = random.randint(0, 10)
if rand >= 4:
print('Send %r to %s' % (message, addr))
self.transport.sendto(data, addr)
else:
print('Send %r to %s' % (message, addr))
self.transport.sendto(data, addr)
loop = asyncio.get_event_loop()
print("Starting UDP server")
# One protocol instance will be created to serve all client requests
listen = loop.create_datagram_endpoint(
EchoServerProtocol, local_addr=('127.0.0.1', 12000))
transport, protocol = loop.run_until_complete(listen)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
transport.close()
loop.close()

Socket Programming Issue - Python

Alright, I've spent about three hours fiddling with socket programming in Python trying to make a simple chat program. I've gotten the client to send text to the server and then, from then client, it repeats the message to it's self. However, I want the message to be sent to the server and then the server, not the client, re-send it to all client's connected. I'm having issues doing this. This is my code so far:
Server Side Code:
import SocketServer
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print "%s wrote:" % self.client_address[0]
print data
socket.sendto(data.upper(), self.client_address)
if __name__ == "__main__":
HOST, PORT = "localhost", 25555
server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler)
server.serve_forever()
Client Side Code:
import socket
import sys
global HOST
global PORT
HOST, PORT = "localhost", 25555
while 1 > 0:
data = raw_input(">".join(sys.argv[1:]))
# SOCK_DGRAM is the socket type to use for UDP sockets
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# As you can see, there is no connect() call; UDP has no connections.
# Instead, data is directly sent to the recipient via sendto().
sock.sendto(data + "\n", (HOST, PORT))
received = sock.recv(1024)
print "Sent: %s" % data
print "Received: %s" % received
Right now your app is instantiating the MyUDPHandler class for each client connection. When the connection is opened you need to store that instance to a static array or queue. Then when the handle() call is made it can loop through all those sockets and send a copy of the data to each of them.
I'd checkout the python documentation; it basically does what your looking to: http://docs.python.org/library/socketserver.html#asynchronous-mixins
And what I'd change from that example (Don't just drop this in; it probably has glaring bugs!):
handlerList = []
class ...
def handle(self):
handlerList.append(self)
while (1):
data = self.request.recv(1024)
if (not data):
break
cur_thread = threading.currentThread()
response = "%s: %s" % (cur_thread.getName(), data)
for x in handlerList:
x.request.send(response)
psudo_code_remove_self_from_handlerList()
Would you like to play with a server that echos packets to all sockets but the original source of the data?
import socket, select
def main():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 8989))
server.listen(5)
sockets = [server]
while True:
for sender in select.select(sockets, [], [])[0]:
if sender is server:
sockets.append(server.accept()[0])
else:
try:
message = sender.recv(4096)
except socket.error:
message = None
if message:
for receiver in sockets:
if receiver not in (server, sender):
receiver.sendall(message)
else:
sender.shutdown(socket.SHUT_RDWR)
sender.close()
sockets.remove(sender)
if __name__ == '__main__':
main()

Categories