python tcp server sending data to multiple clients - python

i am having trouble trying to send data to all clients connected on my python tcp chat server. i know how to get the message/data to send right back to the person who sent it but it just won't send back if i have multiple clients. this is my server so far:
host = '127.0.0.1'
port = 4446
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind( (host, port) )
s.listen(backlog)
clients = [s]
while 1:
inputReady, outputReady, exceptReady = select.select(clients, [], [])
for x in inputReady:
if x == s:
csock, addr = s.accept()
clients.append(csock)
else:
data = x.recv(size)
if data:
for i in clients: #problem i believe is in here but i
i.send(data) #dont know how to fix it
else:
x.close()
clients.remove(x)
s.close()
i am using node.js for the client side and its very simple so far and i dont think its the problem:
var net = require('net');
var readline = require('readline');
var host = process.argv[2];
var port = process.argv[3];
var username = process.argv[4];
var client = new net.Socket();
client.connect(port, host, function(){
var type = "connect";
var sender = username;
var msg = "has connected";
var s = type + ':' + sender + ':' + msg;
var length = s.length;
client.write(length + " " + s);
});
client.on('data', function(data){
console.log(data.toString('UTF-8'));
});

The problem is that you are sending on all sockets, including the server socket (s). Ignoring other potential problems, you can do a quick fix by doing this:
for i in clients:
if i is not s:
i.send(data)

Related

How to send a base64 encoded image via tcp from python to node js?

I am basically working on a project and got stuck at this point. I tried normal tcp but later found that the image was partially transported of max length around 65,000 at node js end. But the total encoded image length is around 3 times of 65000 at python side. The image is basically a screen-shot of my desktop of resolution around 1920 x 1020.
Here is my python side code
import socket
HOST = '127.0.0.1' # Standard loopback interface address (localhost)
PORT = 9898 # Port to listen on (non-privileged ports are > 1023)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
print("-- start --")
conn, addr = s.accept()
print("-- accepted --")
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
print("R : ", data)
if not data:
break
print("sending data")
# b64str is a pre computed string of length around 65000*3
conn.sendall(bytes(b64str, 'utf-8'))
Here is Node js side code
client.connect(9898, '127.0.0.1', function() {
console.log('CONNECTED : img-data-channel');
});
// buff is a buffer queue that stores the base64 encoded string
client.on('data', function(data) {
str_data = String.fromCharCode.apply(null, data);
buff.push_data(str_data);
// console.log("Received: img-data type : ", typeof(str_data), " size : ", str_data.length) ;
});
client.on('close', function() {
console.log('DISCONNECTED : img-data-channel');
});
Thankyou in advance.

i want to receive string from python server

I'm making an application using android and Python.
android is client
python is server
i send image file to python and want to receive string from server
but No strings are coming from the server.
socketIn.readLine() This part does not work.
try { // 소켓을 생성하고 입출력 스트립을 소켓에 연결
clientSocket = Socket(ip , port)
Log.d("Socket>>>>>>", "ip and port open Success!!!!!")
//val inputStream = clientSocket.getInputStream()
val tempfile = file
try{
socketIn = BufferedReader(InputStreamReader(clientSocket.getInputStream(), "UTF-8"))
//socketOut = PrintWriter(BufferedWriter(OutputStreamWriter(clientSocket.getOutputStream())),true)
dis = DataInputStream(FileInputStream(tempfile))
dos = DataOutputStream(clientSocket.getOutputStream())
val buf = ByteArray(1024)
var read_length : Int = 0
do {
read_length = dis.read(buf)
if(read_length == -1)
break
dos.write(buf)
dos.flush()
} while(read_length > 0)
var line : String?
var StringBuilder = StringBuilder()
do {
line = socketIn.readLine()
if(line == null)
break
StringBuilder.append(line)
}while(line != null)
onApiResult(line)
} catch (e : Exception){
Log.d("error", "${e}")
onApiFailed()
} finally {
clientSocket.close()
}
this is my android client code. client send the image to python server using tcp.
The image is sent well but the string does not come.
There is an error here line = socketIn.readLine()
please tell me how to fix it
from socket import *
serverPort = 8000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('123.234.345.456', serverPort))
serverSocket.listen(1)
print('The server is ready to receive')
msg = "hi"
while True:
connectionSocket, addr = serverSocket.accept()
img_file = open('hi.jpg', "wb")
while True:
sentence = connectionSocket.recv(1024)
data = sentence
img_file.write(sentence)
if sentence:
print("recving IMg....")
print(sentence)
sentence = connectionSocket.recv(1024)
img_file.write(sentence)
else:
print('Done')
img_file.close()
break
connectionSocket.sendall(bytes(msg, 'UTF-8'))
connectionSocket.close()
Just a guess -- you are sending binary data, but your client code uses java Reader/Writer classes (dedicated to reading text-like data). Use Streams, instead of Reader/Writer. There is no notion of 'endOfLine' when reading binary data. Also note, that client call to 'readLine()' assumes client platform dependent end-of-line, whatever it may be. If server and client platform differ, it will never work.

Keep the server open when client disconnect Python

I'm currently working on a project and I need to use socket (python). My problem is :
- When the client disconnect, my server disconnect too. But I don't want this. I want the server to stay alive all the time, how can I do that ?
If I close the client I would like the server to keep alive
Here is my code :
Client :
import socket
hote = "localhost"
port = 12800
connexion_avec_serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connexion_avec_serveur.connect((hote, port))
print("Established {}".format(port))
msg_a_envoyer = b""
while msg_a_envoyer != b"fin":
msg_a_envoyer = input("> ")
msg_a_envoyer = msg_a_envoyer.encode()
connexion_avec_serveur.send(msg_a_envoyer)
msg_recu = connexion_avec_serveur.recv(1024)
print(msg_recu.decode())
print("Close connection")
connexion_avec_serveur.close()
Server :
import socket
import select
hote = ''
port = 12800
connexion_principale = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connexion_principale.bind((hote, port))
connexion_principale.listen(5)
print("rece {}".format(port))
serveur_lance = True
clients_connectes = []
while serveur_lance:
connexions_demandees, wlist, xlist = select.select([connexion_principale],
[], [], 0.05)
for connexion in connexions_demandees:
connexion_avec_client, infos_connexion = connexion.accept()
clients_connectes.append(connexion_avec_client)
clients_a_lire = []
try:
clients_a_lire, wlist, xlist = select.select(clients_connectes,
[], [], 0.05)
except select.error:
pass
else:
for client in clients_a_lire:
msg_recu = client.recv(1024)
msg_recu = msg_recu.decode()
print("Recu {}".format(msg_recu))
client.send(b"5 / 5")
if msg_recu == "fin":
serveur_lance = False
Excuse my english.
Thanks for your help
I suspect it's not when the client disconnects, as such, but when the client sends "fin". That's when the client's loop stops, and also when the server's loop stops. The only thing in the code you've posted that changes the value of serveur_lance is when the client sends "fin":
while serveur_lance:
...
if msg_recu == "fin":
serveur_lance = False
So the moment someone types fin into the client, the server will also get the command to stop.
Instead of changing the value of serveur_lance in your server code, you probably want to close that specific connection and remove it from the clients_connectes list.

Dns response doesn't reach destination

I'm trying to write my own dns server with python code. So, I send dns request from my computer to my gateway (which i get from ipconfig-> default gateway). The request reaches to my server and when I'm trying to response, it seems like the dns response not reaching the client destination (at this case my computer).
On the client i get "Standard query response Server failure" instead of regular dns response.
What am I doing wrong? How can I fix it?
Client wireshark:
Server wireshark:
Client code:
def ConvertToDnsNameFormat(name) :
result = ""
lock = 0
name += "."
length = len(name)
for i in range(0, length) :
if name[i] == "." :
result += chr(i-lock)
while lock < i :
result += name[lock]
lock = lock + 1
lock = lock + 1
result += (chr(0))
return result
hostname= "random1231.ns.cs.colman.ac.il"
hostname = ConvertToDnsNameFormat(hostname)
format = '!HHHHHH' + str(len(hostname)) + 'sHH' # the DNS query format
dnsMessage = pack(format, 1234, 256, 1, 0, 0, 0, hostname, 1, 1) # create the massage
#my gateway
HOST_IP = "192.168.1.1"
PORT = 53
AF = socket.AF_INET
TYPE = socket.SOCK_DGRAM
PROTO = socket.IPPROTO_UDP
mySocket = socket.socket(AF, TYPE, PROTO)
mySocket.sendto(dnsMessage, (HOST_IP, PORT))
(resp, address) = mySocket.recvfrom(1024)
Server code:
I took this code from here
import socket
class DNSQuery:
def __init__(self, data):
self.data=data
self.dominio=''
tipo = (ord(data[2]) >> 3) & 15 # Opcode bits
if tipo == 0: # Standard query
ini=12
lon=ord(data[ini])
while lon != 0:
self.dominio+=data[ini+1:ini+lon+1]+'.'
ini+=lon+1
lon=ord(data[ini])
def respuesta(self, ip):
packet=''
if self.dominio:
packet+=self.data[:2] + "\x81\x80"
packet+=self.data[4:6] + self.data[4:6] + '\x00\x00\x00\x00' # Questions and Answers Counts
packet+=self.data[12:] # Original Domain Name Question
packet+='\xc0\x0c' # Pointer to domain name
packet+='\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Response type, ttl and resource data length -> 4 bytes
packet+=str.join('',map(lambda x: chr(int(x)), ip.split('.'))) # 4bytes of IP
return packet
if __name__ == '__main__':
ip='192.168.1.1'
print 'pyminifakeDNS:: dom.query. 60 IN A %s' % ip
udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udps.bind(('10.10.250.40',53))
try:
while 1:
data, addr = udps.recvfrom(1024)
p=DNSQuery(data)
udps.sendto(p.respuesta(ip), addr)
print 'Respuesta: %s -> %s' % (p.dominio, ip)
except KeyboardInterrupt:
print 'Finalizando'
udps.close()
That's probably because the server is failing. Try to do a ping to random1231.ns.cs.colman.ac.il, you'll see that with that domain, the response is server failure:
So, the miniDNS program is not capturing the DNS requests. Did you try installing it on your localhost address? (127.0.0.1, say port 4567) and configure your DNS service to that address.

Receive more than one message on more than one port Echo Server python

I am writing a echo server and client in Python, that implements a simple number guessing game. I know how to multiplex using select, that's fine. The other server I wrote achieves this. But now I am writing a new server (which is fairly similar), however it accepts connections from two ports rather than one, one port for player client, and one for admin which I will use eventually for the who command, returning all connected players.
My problem is, that after sending the initial greetings message, the clients receive feedback from the server on the first send, recv. But after that I cannot send any more messages to server (nothing gets sent from the clients), I have been searching and playing around for hours, to no avail. Any help would be appreciated. Thanks!
# MULTIPLEX SERVER
import socket, select, time, random, ssl, sys, os
# VARS
EXP = 1
HOST = '127.0.0.1'
PORT_P = 4000
PORT_A = 4001
BUFFSZ = 1024
BKLOG = 5
GREETS = 'Greetings'
INPUTS = []
OUTPUTS = []
CLIENT_ADDRS = {}
CLIENT_ANS = {}
CLIENTS = ""
_adm_rtnMSG = 'Admin_Greetings'
# Function to determine how far the player is
# from the chosen random number
def Within(value, target):
diff = abs(target - value)
if diff > 3:
return 'Not even close, youth!'
else:
return 'Ooh, not to far: ' + str(diff) + ' away, keep trying...'
# END_FUNCTION
print('Server up and running...\n')
try:
for p in PORT_P, PORT_A:
INPUTS.append(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
INPUTS[-1].setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
INPUTS[-1].bind((HOST, p))
INPUTS[-1].listen(BKLOG)
except socket.error(value, message):
if INPUTS[-1]:
INPUTS[-1].close()
INPUTS = INPUTS[:-1]
print('Failure to open socket: ' + message)
sys.exit(1)
while True:
READ_IO, WRITE_IO, ERROR = select.select(INPUTS, OUTPUTS, INPUTS)
for r in READ_IO:
for p in INPUTS:
if r is p:
(acpt_sock, addr) = p.accept()
print('Connection established with ', acpt_sock.getsockname())
CLIENT_ADDRS[acpt_sock] = addr
CLIENT_ANS[acpt_sock] = random.randrange(1, 20)
else:
data = acpt_sock.recv(BUFFSZ).decode()
acpt_sock.setblocking(0)
if data:
if 'Hello' in data:
print(CLIENT_ADDRS[acpt_sock], ' random number is: ', CLIENT_ANS[acpt_sock])
acpt_sock.send(b'Greetings\nGuess a random number between 1 & 20')
# drop elif here for admin cmd
elif 'Hi' in data:
acpt_sock.send(_adm_rtnMSG.encode())
else:
if int(data) == CLIENT_ANS[acpt_sock]:
acpt_sock.send(b'That was correct, Well done!')
else:
acpt_sock.send(str(Within(int(data), CLIENT_ANS[acpt_sock])).encode())
else:
print('Closing Connection # ', addr)
INPUTS.remove(acpt_sock)
acpt_sock.close()
del CLIENT_ADDRS[acpt_sock]
# PLAYER CLIENT
import socket
import re
# INIT VARS
HOST = '127.0.0.1'
PORT = 4000
INITSTR = 'Hello'
BUFF = 1024
# Set up socket
sender = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sender.connect((HOST, PORT))
sender.send(bytes((INITSTR), "ascii"))
print("Kirby Prompt FTW!\nConnected to Server via", HOST, "::", PORT, '\n')
rtnMSG = sender.recv(BUFF).decode()
print(rtnMSG)
# Simple loop to keep client alive
# to send and receive data from the server
while 'correct' not in rtnMSG:
_guess = input("(>',')> ")
sender.send(bytes((_guess), "ascii"))
rtnMSG = sender.recv(BUFF).decode()
print(rtnMSG)
sender.close()
# ADMIN CLIENT
import socket
import re
import ssl
# INIT VARS
HOST = '127.0.0.1'
PORT = 4001
INITSTR = 'Hi'
BUFF = 1024
# Set up socket
adm_sender = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
adm_sender.connect((HOST, PORT))
adm_sender.send(bytes((INITSTR), "ascii"))
print("Connected to Server as Admin via", HOST, "::", PORT, '\n')
rtnMSG = adm_sender.recv(BUFF).decode()
print(rtnMSG)
while True:
cmd = input('$ ')
adm_sender.send(bytes((cmd), "ascii"))
rtnMSG = adm_sender.recv(BUFF).decode()
print(rtnMSG)
adm_sender.close()

Categories

Resources