Client socket not receiving data correctly - python

I've tried looking about for an answer but I can't seem to find one that answers my specific problem.
Perhaps I don't know how to articulate the problem correctly.
I think I've pinpointed what it is, but the thing is I just don't know how to fix it.
EDIT: I was trying to use two clients on one TCP Socket. Can't do that. I'll have to think of another way. Solved, I guess.
So what I've got is are
1: Two Clients
2: One Server
The objective is this:
Have the server distribute new usernames to all the clients as they connect.
This is what happens when I run the program:
Server: Define Host, and Port, initialize it. Check
Client 1: Connects to the server. Check
Client 1: Once connected, sends a string to the server. Check
Server: Receives a string, checks if the string is in a list is created. If it is: Pass, if it's not, send to everyone the new string. Check
Client 1: [Now waiting to receive data] Recieves data, checks if the string received matches the one it sent. If it does, print("It's one of ours!"), else, make the new string = to Client 2 Username. Check
Client 2: Connects to server: Check
Server: [If it receives a string, prints it.] (Works) Checks if the new string is in the list. [It isn't] So It sends the new username to everyone, and then prints ("Sent to everyone") Check
But, when client 2 receives the string, it prints it. However, client 1 never recives the string.
And when running client one in IDLE, I noticed something went wrong as Client 1 tried to receive the data. (The while loop that the data = s.recv began looping real fast, instead of waiting)
I've asked around in chat, but it seems nobody's around right now. I've tried looking this up but I really can't find an answer. What I suspect is happening is that when my server sends to 'connection' the second time, it somehow overrides the original client connection.
Here's my server code:
from socket import *
import threading
import os
import csv
Username_List = []
host = input("Host: ")
port = input("Port: ")
ss = socket(AF_INET,SOCK_STREAM)
ss.bind((host,int(port)))
ss.listen(2)
while True:
try:
connection,address = ss.accept()
data = connection.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data in Username_List:
pass
else:
Username_List.append(translated_data)
connection.sendall(translated_data.encode())
print("Sent new username to everyone")
except IOError:
connection.close()
print("An exception with a connected user occured")
break
And here is my client code: [The only difference between client 1 and 2 is I changed the username variable]
# Sample Username Client Service Handler.
from socket import *
import threading
import os
import csv
Username = ("Owatch")
host = input("Host: ")
port = input("Port: ")
try:
ss = socket(AF_INET,SOCK_STREAM)
ss.connect((host,int(port)))
except IOError:
print("Aw no man")
ss.send(Username.encode())
while True:
try:
print("Waiting to Recieve Data")
data = ss.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data == Username:
print("It's one of ours!")
else:
Client_Username = translated_data
print (Client_Username)
except Exception as e:
print (vars(e))
If you could please help I'd be grateful.
If you know of an answer to my question that's already been asked, please tell me and I'll remove this post to avoid breaking rules. Thanks!

Right then I started with what you had then changed it till it worked what I've done is created a client class which starts a thread with each connection and adds it to a list of threads (please if I'm doing something horribly wrong smarter people correct me), the thread runs gets some data checks if that's in the list of user names if its not sends out a message to all the clients in the thread list with that name then the thread just chills out. Anyway on to the code.
SERVER!!!
import csv
class client(threading.Thread):
Username_List = []
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
def run(self):
print "Client thread started"
data = self.conn.recv(1024)
print "Received: {0}".format(data)
if data in client.Username_List:
self.send_msg("Welcome Back!")
else:
for cnt in threadz:
cnt.send_msg(data)
print("Sent new username to everyone")
client.Username_List.append(data)
while True:
# dont need nothing now
pass
def send_msg(self,msg):
self.conn.send(msg)
host = input("Host: ")
port = input("Port: ")
ss = socket() #AF_INET,SOCK_STREAM)
ss.bind((host,int(port)))
print "Server Opening on port: {0}".format(port)
ss.listen(2)
threadz = []
print "Begining Wait for connections"
while True:
try:
connection, address = ss.accept()
print "Got ONE!"
c = client(connection)
print "Recevied connection from:{0} On port:{1}".format(address[0],address[1])
c.start()
threadz.append(c)
print "Client appended to threadz, currently {0} threadz active".format(len(threadz))
except IOError,KeyboardInterrupt:
connection.close()
print("An exception with a connected user occured")
break
The CLIENT:
# Sample Username Client Service Handler.
from socket import *
import threading
import os
import csv
Username = ("ShyGuy")
host = input("Host: ")
port = input("Port: ")
try:
ss = socket() #AF_INET,SOCK_STREAM)
ss.connect((host,int(port))) #I was using ("localhost",1234) for testing
ss.send(Username)
except IOError:
print("Aw no man")
print("Waiting to Recieve Data")
while True:
try:
data = ss.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data == Username:
print"Name: {0} has been registered on server!".format(translated_data)
else:
Client_Username = translated_data
print "New client name received: {0}".format(Client_Username)
except Exception as e:
print (vars(e))
That works on python 2.7 with two clients locally. Needs to use a semaphore to stop the threads printing at the same time as the main server loop prints: http://en.wikipedia.org/wiki/Semaphore_(programming)
This code does nothing graceful with client disconnects, but once you can work with the exceptions that a raised when that happens I'm sure you'll learn some more.

Related

Infinite loading on conn.recv python socket

I'm currently trying to make a socket connection between a server and multiple clients in Python.
In short, I have a function that is used to test if the clients are still online or dead.
To do so, i'm sending a white space to the client, and if no exception occures, it's all good, and if there is an exception I'm deleting the client from the client list.
Everything works fine, except when the client is switching network (for exemple I switch from a 2GHz network, to the same network in 5GHz). Then, the conn.recv is creating an infinite loading because the client is not receiving the data that was sent in conn.send. As a precision, both of the network where I was connected works well separately. The only solution that I found for now is restarting the server when such an event occurs..
Here is the part of the code that doesn't work (server):
# Check for clients availability
def check_clients(self, UUID):
invalid_conn = []
print(f"(UUID: {UUID}) Checking for dead clients")
if UUID not in self.all_connections: return False
# Delete dead clients for specific user (UUID)
self.socket.settimeout(2) # Also tried to set a timeout, doesn't work
print('setting timeout')
for i, conn in enumerate(self.all_connections[UUID]):
try:
print('sending blank cmd')
conn.send(str.encode(' '))
cwd = str(conn.recv(20480)) # This is the line that causes infinite loop
print('got cwd:',cwd) # This is what we are excepting from the client
except:
print('appening invalid conn to list:',conn)
invalid_conn.append(conn)
continue
print('removing timeout')
self.socket.settimeout(None)
for i in invalid_conn:
client_id = self.all_connections[UUID].index(i)
print(f'(UUID: {UUID}) Could not reach client on conn list, removing {self.all_addresses[UUID][client_id]}')
del self.all_connections[UUID][client_id]
del self.all_addresses[UUID][client_id]
print(f"(UUID: {UUID}) Dead clients check finished")
return
And here is the part of the client that should receive the server information:
# Receive commands from server
def receive_commands(self):
while True:
print("Listening for commands")
output_str = None
data = self.sock.recv(1024)
print('data:',data)
if len(data) > 0:
try:
cmd = data[:].decode("cp850")
# Do such and such events with cmd, this is a shortened version for demo
output_str = str(f'received: {cmd} from server', "cp850")
except Exception as e:
output_str = f"Command failed to execute: {str(e)}"
if output_str == None:
raise ConnectionError ("No response from server")
else:
self.print_output(output_str)
print(f"Input command: {data[:].decode('cp850')}")
print(f"Output -> {output_str}\n")
self.sock.close()
return
Please ask me if you need any more info, thank you for your help.

Python Socket - Send/Receive messages at the same time

Basically I have been working on a simple chat room using socket and thread. In my client I can receive and send messages, my issue is that one comes before another in a loop, so if I am sending a message I will only receive data once I have sent a message. I want it to work like any other chat room, where I could receive a message when I am sending a message, any help will help greatly. This is my basic client:
import socket
import sys
###########
HOST = '25.0.18.52'
PORT = 9999
###########
name = input("Enter your name: ")
s = socket.socket()
s.connect((HOST,PORT))
while 1:
message = input("Message: ")
s.send("{}: {}".format(name, message).encode('utf-8'))
data = s.recv(1024)
a = data.decode("utf-8")
print(a)
You should keep 2 threads: one for listening and the other for receiving. In your while loop, you should remove the listener part, and keep the code in a different thread. This way you can receive and type on the console at the same time.
def recv():
while True:
data = s.recv(1024).decode()
if not data: sys.exit(0)
print data
Thread(target=recv).start()

Just get one last value from socket

I send data to socket on one side every second, but I can read that data on another side in any moment. Here's the writer:
from settings import Config
filename = Config.NAVIGATION_SOCKET_FILE
client = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
client.settimeout(None)
while True:
try:
client.connect(filename)
break
except Exception:
continue
messages = ["$GPRMC,125504.049,A,5542.2389,N,03741.6063,E,0.06,25.82,200906,,,*17",
"$GPRMC,155604.049,A,5542.2389,N,03741.6063,E,0.06,25.82,200906,,,*19",]
while True:
msg = random.choice(messages)
client.send(msg)
print msg
time.sleep(1)
And here's reader:
navigation_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
if os.path.exists(app.config['NAVIGATION_SOCKET_FILE']):
os.remove(app.config['NAVIGATION_SOCKET_FILE'])
navigation_socket.bind(app.config['NAVIGATION_SOCKET_FILE'])
class NavigationInfo(restful.Resource):
def get(self):
msg = navigation_socket.recv(1024)
regex = re.compile(r"^\$GPRMC,(?P<time>\d{6}\.\d{3}),(?P<status>A|V),"
r"(?P<latitude>\d{4}\.\d{4}),(?P<lat_n_s>N|S),"
r"(?P<longitude>\d{5}\.\d{4}),(?P<long_e_w>E|W),"
r"(?P<hor_speed>\d+.\d+),(?P<track_angle>\d+.\d+),"
r"(?P<date>\d{6}),(?P<magnetic_declination>\d+\.\d+)?,"
r"(?P<magnetic_decl_direction>\d)?,"
r"(?P<mode>A|D|E|N)?\*(?P<checksum>\d\d)")
result = regex.match(msg)
navigation_info = result.groupdict()
return navigation_info
So the first problem is that writer just stops writing data to socket when buffer is full (at least that's what I see) and when I request data on the other side, it's too old.
Can just I store one value in buffer and then rewrite it? Or maybe I'm getting it all wrong?
I think that you are using the solution in reverse.
Instead of pushing messaging, while not pulling messages ?
Your server may look like:
Wait for a connection
Give a random message
go to step 1
And your client may just connect to the server when he needs a message.
In your case, the connection is "opened all the time", in my solution the socket is opened only when needed. and closed right after the message is delivered.

socket programming for beginner - server creating

I start learning socket programming and I created a simple server that should replay everything I send to him back to me.
And its work work and I manage to telnet to it and write things.
but I have two problems with my code:
First, every sigh I hit on the keyboard get immediately send and I get it back. it doesn't wait until I press enter.
Second, when I print to the client 'Welcome to the server. Type something and hit enter\n\n' the client see the cmd imput cursor in the middle of the new line, and not in the start of it.
here is part of my code:
#server in local host
class ClientConnection(threading.Thread):
def __init__(self,conn):
threading.Thread.__init__(self)
self.conn = conn
def run(self):
clientthread(self.conn)
#create a new thread for each connection
def clientthread(conn):
conn.send('Welcome to the server. Type something and hit enter\n\n'.encode())
while True:
data = conn.recv(2048).decode()
replay = 'OK....' + data
if not data:
break
conn.sendall(replay.encode())
conn.close()
... #socket get close in the end
How do I make the server response only if I the client press enter? I try to check if the recive = '\n' but it doesn't seem to work.
I will appreciate any help and tips
edit: my second question answard simply
Yes, the client will often send you data as the user types rather then only when the user hits return. Thus, it is up to you to check if the data has a return, and only respond if it does.
data = ""
while True:
chunk = conn.recv(2048).decode()
if not data:
break
# try to separate the chunk by newline, to see if you got one.
while True:
split = chunk.split("\r\n", num=1)
data += split[0]
if len(split) == 1:
break
# Now we have a completed newline, so send the response
replay = 'OK....' + data
conn.sendall(replay.encode())
data = ""
conn.close()

My chat client freezes up after beginning threads

I made a better chat client following help from people:
They told me that if I didn't want to be blocked on .recv when waiting for messages, I would need to use threads, classes, functions, and queues to do so.
So I followed some help a specific person gave me where I created a thread from a class and then defined a function that was supposed to read incoming messages and print them.
I also created a function that allows you to enter stuff to be sent off.
Thing is, when I run the program. Nothing happens.
Can somebody help point out what is wrong? (I've asked questions and researched for 3 days, without getting anywhere, so I did try)
from socket import *
import threading
import json
import select
print("Client Version 3")
HOST = input("Connect to: ")
PORT = int(input("On port: "))
# Create Socket
s = socket(AF_INET,SOCK_STREAM)
s.connect((HOST,PORT))
print("Connected to: ",HOST,)
#-------------------Need 2 threads for handling incoming and outgoing messages--
# 1: Create out_buffer:
Buffer = []
rlist,wlist,xlist = select.select([s],Buffer,[])
class Incoming(threading.Thread):
# made a function a thread
def Incoming_messages():
while True:
for i in rlist:
data = i.recv(1024)
if data:
print(data.decode())
# Now for outgoing data.
def Outgoing():
while True:
user_input=("Your message: ")
if user_input is True:
Buffer += [user_input.encode()]
for i in wlist:
s.sendall(Buffer)
Buffer = []
Thanks for taking a look, thanks also to Tony The Lion for suggesting this
Take a look at this revised version of your code: (in python3.3)
from socket import *
import threading
import json
import select
print("client")
HOST = input("connect to: ")
PORT = int(input("on port: "))
# create the socket
s = socket(AF_INET, SOCK_STREAM)
s.connect((HOST, PORT))
print("connected to:", HOST)
#------------------- need 2 threads for handling incoming and outgoing messages--
# 1: create out_buffer:
out_buffer = []
# for incoming data
def incoming():
rlist,wlist,xlist = select.select([s], out_buffer, [])
while 1:
for i in rlist:
data = i.recv(1024)
if data:
print("\nreceived:", data.decode())
# now for outgoing data
def outgoing():
global out_buffer
while 1:
user_input=input("your message: ")+"\n"
if user_input:
out_buffer += [user_input.encode()]
# for i in wlist:
s.send(out_buffer[0])
out_buffer = []
thread_in = threading.Thread(target=incoming, args=())
thread_out = threading.Thread(target=outgoing, args=())
thread_in.start() # this causes the thread to run
thread_out.start()
thread_in.join() # this waits until the thread has completed
thread_out.join()
in your program you had various problems, namely you need to call the threads; to just define them isn't enough.
you also had forgot the function input() in the line: user_input=input("your message: ")+"\n".
the "select()" function was blocking until you had something to read, so the program didn't arrive to the next sections of the code, so it's better to move it to the reading thread.
the send function in python doesn't accept a list; in python 3.3 it accepts a group of bytes, as returned by the encoded() function, so that part of the code had to be adapted.

Categories

Resources