Thread not starting - no prompt for user input (Python) - python

I'm implementing a simple messaging application using Python. I've defined a client CClient which instantiates a CMsgGateway and then begins a thread which asks the user for input (while 1). The client is as follows:
from msginterface import CMsgGateway
class CClient():
def __init__(self):
self.port = 2400
self.msgGate = CMsgGateway(self.port)
Thread(target=self.inputMsg).start()
def inputMsg(self):
while 1:
msg = input("Enter message:")
self.msgGate.sendMsg(msg)
if __name__ == '__main__':
cmdchat = CClient()
The message gateway listens for messages being received in a separate thread (while 1). This class is defined as:
from threading import Thread
import socket, struct, sys
class CMsgGateway():
def __init__(self, port):
self.port = port
print("Listening on port " + str(self.port) + ".\n")
Thread(target=self.serve).start()
def serve(self):
while 1:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind(("", self.port))
self.sock.listen(1)
self.rcvMsg()
def rcvMsg(self):
serverSocket, info = self.sock.accept()
while 1:
try:
buf = bytearray(4000)
view = memoryview(buf)
bytes = serverSocket.recv_into(view, 4000)
if bytes:
stx = view[0]
Size = view[1:3]
bSize = Size.tobytes()
nTuple = struct.unpack(">H", bSize)
nSize = nTuple[0]
message = view[0:3+nSize]
messageString = message.tobytes().decode("utf-8").strip()
print("Received message:\n\n" + messageString)
sys.stdout.flush()
else:
break
except socket.timeout:
break
def sendMsg(self, msgToSend):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
host = socket.gethostname()
self.sock.connect((host, self.port))
self.sock.send(msgToSend.encode())
self.sock.close()
When I run the program the thread within CMsgGateway begins, listening for messages. However, as far as I can tell the thread within CClient, the inputMsg method, does not begin (I see no prompt to enter input e.g. "Enter message" is not displayed).
Could someone please help me figure out what is wrong with this? Many thanks.

Related

BlockingIOError: [Errno 11] Resource temporarily unavailable two clients one server sockets python

I am trying to simply send messages from two client sockets to one server socket. When I start up the server socket, it works fine, and then when I start up each of the two client sockets (I'm using 3 different terminal windows) everything works fine. If I start up the server and one client, I can send messages from the client to the server. If I then start up the second client, I can send messages from the second client to the server, however now if I go back and try to send messages from the first client to the server, I get a " BlockingIOError: [Errno 11] Resource temporarily unavailable ". What is the problem?
clientclass.py:
from itertools import count
import select
import random
import threading
import time
class Client(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.host = "127.0.0.1"
self.port = 65432
def run(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.id = random.randrange(0, 1000)
print(f"client id {self.id} connected")
self.sock.connect((self.host, self.port))
while True:
text = input('m: ')
self.sock.sendall(text.encode())
server.py:
import socket
from itertools import count
import select
from _thread import start_new_thread
import threading
import time
from queue import Queue
class server(threading.Thread):
def __init__(self):
self.host = "127.0.0.1"
self.port = 65432
threading.Thread.__init__(self)
def run(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
self.sock.listen(5)
self.sock.setblocking(0)
print(f"server instantiated")
inputs = [self.sock]
outputs = []
message_queues = {}
while inputs:
inputready,outputready,exceptready = select.select(inputs,outputs,inputs)
for input_item in inputready:
if input_item is self.sock:
conn, addr = self.sock.accept()
print("New connection from: ", addr)
conn.setblocking(0)
inputs.append(conn)
else:
data = conn.recv(1024)
if data:
print("Client: " + data.decode())
#message_queues[input_item].put(data)
if input_item not in outputs:
outputs.append(input_item)
else:
if input_item in outputs:
outputs.remove(input_item)
inputs.remove(input_item)
input_item.close()
class Message_Sender(threading.Thread):
def __init__(self, client):
threading.Thread.__init__(self)
self.client = client
def run(self):
while True:
text = input('m: ')
server.conn.sendall(text.encode())
server = server()
server.start()
msg = Message_Sender(server)
msg.start()
client instances:
import clientclass
client = clientclass.Client()
client.start()
I saw your code and I think I have solved the problem you might have
I changed some code In a way It receives multiple clients at the same time
server.py:
import socket
from itertools import count
import select
from _thread import start_new_thread
import threading
import time
from queue import Queue
class server(threading.Thread):
def __init__(self):
self.host = "127.0.0.1"
self.port = 65432
threading.Thread.__init__(self)
def run(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
print(f"server instantiated")
inputs = [self.sock]
outputs = []
message_queues = {}
while True:
self.sock.listen(5)
conn, addr = self.sock.accept()
receive = threading.Thread(target=self.receive_data, args=(conn,))
receive.start()
inputs.append(conn)
def receive_data(self, conn):
while True:
data = conn.recv(1024)
if data:
print("Client: " + data.decode())
# do something
class Message_Sender(threading.Thread):
def __init__(self, client):
threading.Thread.__init__(self)
self.client = client
def run(self):
while True:
text = input('m: ')
server.conn.sendall(text.encode())
server = server()
server.start()
msg = Message_Sender(server)
msg.start()
I have made a loop inside the run function, when someone tries to connect it will make a new thread to receive their messages. it wasn't clear to me what you wanted to do with the variables inputs and input_item, ect. but I think you can get really far with this. If you still have any problems feel free to reach out.

How to make a fast continuous stream of data with socket on Python?

I am writing a code where an arduino reads data from an accelerometer, passes it to a python script and then that computer running python sends the data to another computer over a socket conneciton. I have written code which can send and recieve one message at a time, slowly, but as soon as I do it bascially as fast as I can (about 100Hz) then the server side only prints the first message, but no more.
Here is the code for my server side:
import socket
class server:
def __init__(self, PORT=9077, MAX_CONNECTIONS=1000, BUFF_SIZE=1024):
self.s = socket.socket()
self.HOST = socket.gethostbyname(socket.gethostname())
self.PORT = PORT
self.MAX_CONNECTIONS = MAX_CONNECTIONS
self.BUFF_SIZE = BUFF_SIZE
self.s.bind((self.HOST, self.PORT))
self.s.listen(self.MAX_CONNECTIONS)
self.recievingData = False
print("Starting a server")
print("IP: " + str(self.HOST))
print("Port: " + str(self.PORT))
def recieveData(self):
self.recievingData = True
while self.recievingData:
print("Waiting for data")
c, addr = self.s.accept()
print(addr)
data = b''
part = c.recv(self.BUFF_SIZE)
data += part
while len(part) > self.BUFF_SIZE:
# print("looping")
part = c.recv(self.BUFF_SIZE)
print(len(part))
data += part
print(data)
c.close()
def stopRecieving(self):
self.revievingData = False
new_server = server()
new_server.recieveData()
and the client side:
class client:
def __init__(self, HOST="192.168.0.51", PORT=9077):
self.s = socket.socket()
self.HOST = HOST
self.PORT = PORT
self.s.connect((self.HOST, self.PORT))
def send_message(self, message):
message = message.encode()
sent = self.s.sendall(message)
print(sent)
and I basically just call send_message every time there is new data to send.
Is there a way to increase the speed at which the server can recieve messages from the same client? Do I need to create multiple threads for recieving data?
My solution to this was using DTP protocol, where you send messages without checking if the data has been recieved. This is achieved using socket.socket(type=SOCK_DGRAM) on the client and server side and using self.s.recvfrom(self.BUFF_SIZE) for recieving data from a client and self.s.sendto(str(message).encode(), (host, port)) for sending data. This way, there is no handshake between the client and the server and it runs much faster.
You just need some error checking from your input data.
For reference, this is my full updated code:
import socket
from socket import SOCK_DGRAM, SO_REUSEADDR
import numpy as np
import threading
class client:
def __init__(self, HOST="192.168.0.51", PORT=9077):
self.s = socket.socket(type=SOCK_DGRAM)
self.HOST = HOST
self.PORT = PORT
def send_message(self, message):
self.s.sendto(str(message).encode(), (host, port))
class server:
def __init__(self, PORT=9077, BUFF_SIZE=1024):
self.s = socket.socket(type=SOCK_DGRAM)
self.HOST = socket.gethostbyname(socket.gethostname())
self.PORT = PORT
self.MAX_CONNECTIONS = MAX_CONNECTIONS
self.BUFF_SIZE = BUFF_SIZE
self.s.bind((self.HOST, self.PORT))
# self.s.listen(self.MAX_CONNECTIONS)
self.recievingData = False
self.recievedData = np.zeros((1,4))
self.thread = threading.Thread(target=self.recieveData)
self.thread.start()
# self.s.setblocking(0)
self.startRecieving()
print("Starting a server")
print("IP: " + str(self.HOST))
print("Port: " + str(self.PORT))
def startRecieving(self):
self.recievingData = True
self.recievedData = np.zeros((1,4))
self.thread = threading.Thread(target=self.recieveData)
self.thread.start()
print("Started reading data")
def stopRecieving(self):
self.recievingData = False
self.thread.join()
print("Stopped reading data")
def recieveData(self):
self.recievingData = True
while self.recievingData:
# print("Waiting for data")
part, addr = self.s.recvfrom(self.BUFF_SIZE)
# print(part, addr)
data = b''
data += part
while len(part) > self.BUFF_SIZE:
# print("looping")
part = self.s.recvfrom(self.BUFF_SIZE)
# print(len(part))
data += part
self.lastData = data
print(data)
as_float = np.array([[float(x.strip()) for x in data.decode().split(',')]])
self.recievedData = np.vstack((self.recievedData, as_float))

Python - socket server receives more data than I sent

I made an app to send to python socket the message "Oleft" when i tilt the phone but the result on console is like:
connection from('192.168.0.101', 33313)
b'Oleft'
b'OleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleft'
b'Oleft'
b'OrightOrightOrightOright'
b'OleftOleftOleftOleftOleftOrightOrightOrightOrightOrightOrightOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleft'
b'OleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleft'
b'OleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleft'
b'OleftOleftOleftOleftOleftOleftOleftOleftOleftOleftOleft'
b'OleftOleft'
It has no way to receive only an b'Oleft' ?
wgremote.py
import socket
class WGRemote:
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = socket.gethostname()
self.port = 10000
self.received = None
def connect(self):
global c, addr
self.sock.bind((self.host, self.port))
self.sock.listen(5)
c, addr = self.sock.accept()
print('connection from' + str(addr))
def setMode(self,mode):
sent = c.send(mode.encode("utf-8"))
def receive(self):
self.received = c.recv(1024)
return self.received
def close(self):
c.close
testApp.py
import socket
import sys
from wgremote import WGRemote
remote = WGRemote()
remote.connect()
remote.setMode('orient')
while True:
data = remote.receive()
print(data)
Because, You wrote print(data) in the while loop :)
while True:
data = remote.receive()
print(data)
If you want to receive only an b'Oleft you can make a filter :
count = 0
while True:
data = remote.receive()
if data == "b'Oleft":
if count < 1:
count = count + 1
print(data)
Or you must send the only an b'Oleft :)

python network threading simple chat, waits for user to press enter then gets messages

so right now in order to receive your message you need to receive one
my teachers instructions are (in the main)"Modify the loop so that it only listens for keyboard input and then sends it to the server."
I did the rest but don't understand this, ... help?
import socket
import select
import sys
import threading
'''
Purpose: Driver
parameters: none
returns: none
'''
def main():
host = 'localhost'
port = 5000
size = 1024
#open a socket to the client.
try:
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSock.connect((host,port))
#exit on error
except socket.error, (value,message):
if clientSock :
clientSock.close()
print "Could not make connection: " + message
sys.exit(1)
thread1 = ClientThread()
thread1.start()
while True:
#wait for keyboard input
line = raw_input()
#send the input to the server unless its only a newline
if line != "\n":
clientSock.send(line)
#wait to get something from the server and print it
data = clientSock.recv(size)
print data
class ClientThread(threading.Thread):
'''
Purpose: the constructor
parameters: the already created and connected client socket
returns: none
'''
def __init__(self, clientSocket):
super(ClientThread, self).__init__()
self.clientSocket = clientSocket
self.stopped = False
def run(self):
while not self.stopped:
self.data = self.clientSocket.recv(1024)
print self.data
main()
I assume your purpose is to create a program that starts two threads, one (client thread) receives keyboard input and sends to the other (server thread), the server thread prints out everything it received.
Based on my assumption, you first need to start a ServerThread listen to a port (it's not like what your 'ClientThread' did). Here's an example:
import socket
import threading
def main():
host = 'localhost'
port = 5000
size = 1024
thread1 = ServerThread(host, port, size)
thread1.start()
#open a socket for client
try:
clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSock.connect((host,port))
except socket.error, (value,message):
if clientSock:
clientSock.close()
print "Could not connect to server: " + message
sys.exit(1)
while True:
#wait for keyboard input
line = raw_input()
#send the input to the server unless its only a newline
if line != "\n":
clientSock.send(line)
# Is server supposed to send back any response?
#data = clientSock.recv(size)
#print data
if line == "Quit":
clientSock.close()
break
class ServerThread(threading.Thread):
def __init__(self, host, port, size):
super(ServerThread, self).__init__()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind((host, port))
self.sock.listen(1)
self.data_size = size
self.stopped = False
def run(self):
conn, addr = self.sock.accept()
print 'Connected by', addr
while not self.stopped:
data = conn.recv(self.data_size)
if data == 'Quit':
print 'Client close the connection'
self.stopped = True
else:
print 'Server received data:', data
# Is server supposed to send back any response?
#conn.sendall('Server received data: ' + data)
conn.close()
if __name__ == '__main__':
main()
And these are the output:
Connected by ('127.0.0.1', 41153)
abc
Server received data: abc
def
Server received data: def
Quit
Client close the connection
You may check here for more details about Python socket: https://docs.python.org/2/library/socket.html?#example

UDP Hole Punching Not Working

I am trying to create a chat program that works by UDP hole punching and connecting directly to a node which is provided by a broker.
The script I have right now works just fine locally. The problems come when I try to use an external address to connect to. I can't figure this out on my own so I was hoping someone here could help me out!
import socket
import json
import landerdb
import threading
class PeerChat:
address = None
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.db = landerdb.Connect("nodes")
self.brok_ip = ""
self.brok_port = 5000
self.nick = "Test"
self.friends = []
def listen(self):
self.command = {
"HERE":self.here,
"MSG":self.msg,
}
global address
self.sock.bind(address)
while True:
msg, addr = self.sock.recvfrom(1024)
try:
data = json.loads(msg)
except:
continue
if data[u'cmd'] in self.command:
threading.Thread(target=self.command[data[u'cmd']], args=(addr, data)).start()
def main(self):
while True:
msg = raw_input("> ")
msg = msg.split()
try:
msg = json.dumps({"cmd":msg[0], "data":' '.join(msg[2:]), "nick":self.nick, "to":msg[1]})
except:
continue
for x in self.db.find("nodes", "all"):
self.sock.sendto(msg, tuple(x['addr']))
def here(self, addr, data):
if not self.db.find("nodes", {"addr":addr}):
self.db.insert("nodes", {"addr":addr})
if data['nick'] in self.friends:
print data['nick'] + " has come online."
def msg(self, addr, data):
if data['to'] == self.nick:
print data['nick']+": "+data['data']
def GetNodes(self):
self.sock.sendto("", (self.brok_ip, self.brok_port))
with open("nodes", 'wb') as file:
while True:
msg, addr = self.sock.recvfrom(1024)
if msg == "\n":
break
file.write(msg)
msg, addr = self.sock.recvfrom(1024)
global address
address = ("0.0.0.0", int(msg))
for x in self.db.find("nodes", "all"):
addr = tuple(x['addr'])
self.sock.sendto(json.dumps({"cmd":"HERE", "nick":self.nick}),addr)
if __name__ == "__main__":
PeerChat().GetNodes()
threading.Thread(target=PeerChat().listen).start()
PeerChat().main()
I haven't tested this code externally yet, because I'm at uni, but I use slightly different lines to setup a UDP connection.
They might give you some ideas...
#!/usr/bin/python
import socket
import struct
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('239.255.60.60', 4876))
mreq = struct.pack("=4sl", socket.inet_aton("239.255.60.60"), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
packet_number = 0
while True:
packet_number += 1
print packet_number
raw_data = sock.recv(1024)
print raw_data
print
I don't fully understand all that, but it works for me.
It was adapted from here. You should read the entire page a couple of times to understand what they are saying. Do a search of the page for 'IP_MULTICAST_TTL' I gather that you need to set socket.IP_MULTICAST_TTL, 33 in sock.setsockopt, where the number is any number > 32. Remember that I am almost as unsure as you are at this stage...

Categories

Resources