Python Messager LAN [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Trying to make a simple python messager, getting quite aconnection unreachable error. I am trying to make it peer2peer. Could anyone also suggest how to make it better, I was thinking of adding a loop of some sort to ask the user for the next message, not sure how to go about doing this however.
Server.py
import socket
s = socket.socket()
host = socket.gethostbyname(socket.gethostname())
port = 1337
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print ("Got connection from", addr)
c.send("Thank you for connecting to {0}".format(host).encode())
msg1 = input("Enter Message: ")
c.send(msg1.encode())
msg2 = input("Enter Message: ")
c.send(msg1.encode())
msg3 = input("Enter Message: ")
c.send(msg1.encode())
msg4 = input("Enter Message: ")
c.send(msg1.encode())
c.close()
Client.py
import socket
s = socket.socket()
host = ""
port = 1337
s.bind((host, port))
print("""
================================================================================
Welcome to Coder77's local internet message for avoiding surveillance by the NSA
================================================================================
The current soon to be encrypted server is {0}
""".format(host))
host = input("Please select the IP you would like to communicate to: ")
print("Now connecting to {0}....".format(host))
try:
s.connect((host, port))
s.listen(5)
while True:
c, addr = s.accept()
msg1 = input("Enter Message: ")
c.send(msg1.encode())
msg2 = input("Enter Message: ")
c.send(msg1.encode())
msg3 = input("Enter Message: ")
c.send(msg1.encode())
msg4 = input("Enter Message: ")
c.send(msg1.encode())
except socket.error:
print ("Host is unreachable")
input("Enter to lose")
s.close()
Thanks.

Simple server (reworked your code a bit):
from threading import *
import socket
s = socket.socket()
host = socket.gethostbyname(socket.gethostname())
port = 1337
s.bind((host, port))
s.listen(5)
def getMainThread():
for thread in enumerate(): # Imported from threading
if thread.name == 'MainThread':
return thread
return None
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.socket = socket
self.address = address
self.start() # Initated the thread, this calls run()
def run(self):
main = getMainThread()
while main and main.isAlive():
message = self.socket.recv(8192).decode('utf-8')
self.socket.send(b"Got your message.. send another one!")
self.socket.close()
while True:
c, addr = s.accept()
client(c, addr)
This server (altho yet basic) will handle multiple clients.
And here's a working client solution:
import socket
print("""
================================================================================
Welcome to Coder77's local internet message for avoiding surveillance by the NSA
================================================================================
The current soon to be encrypted server is {0}
""".format(host))
host = input("Please select the IP you would like to communicate to: ")
print("Now connecting to {0}....".format(host))
sock = socket.socket()
try:
sock.connect((host, 1337))
while True:
message = input("Enter Message: ")
if message == 'quit':
break
sock.send(bytes(message, 'UTF-8'))
recieved = sock.recv(8192).decode('utf-8')
print('Server responded with:', recieved)
except socket.error:
print ("Host is unreachable")
sock.close()
Short about the server.
The point of a server is to handle multiple clients, this one will thanks to some basic threads.
Each client that connects, gets accepted and then thrown into a thread (when you call client() it will initate it's own thread and the rest of the application will continue along side of that clients thread).
All client threads should die when the main thread dies, for instance if you throw a CTRL+C it shouold break but the error handling there needs more work, and you'll most likely end up with a "Socket already in use" because of lack of perfection in the cleanup department.
But you get the idea and you'll have to learn to do some work yourself :)
The client,
as long as you don't write "quit" it will first and for more connect to a server in the cleanest way possible, and will forever SEND+Recieve messages to and from the server, until (as mentioned) you write "quit". That will disconnect and end your program.
Now, All this does, is send a message to the server and it auto-replies.
Consider creating something such as:
clients = {}
...
clients[self.addr[0]] = self.socket
or even
clients['Torxed'] = self.socket
Enabling yo to do stuff like:
message = self.socket.recv(8192).decode('utf-8')
toWho = message.split(': ', 1)[0]
if toWho in clients:
clients[toWho].send(bytes(message, 'UTF-8'))
So that when a client writes 'Torxed: Hey whats up mate?' it will get redirected to that client socket. That's just a completely simple and plain idea to show you what you should or at least could do.
Things that might be confusing
I noticed you wrote s = ... and c = ... quite a lot.
And you had some double-socket thing going on in the client..?
Calling things for what they are is usually good practice.. for instance,
In the server you could call the socket server but never s.
Or you just keep it clean and simple and call it socket in both ends except in some rair occations where you might create multiple server-instance sockets for whatever reason (bridging servers and what not).
And remember, the easier and short the solution is.. The more probable it is that you'll remember why and how you solved it. Don't go overboard on solutions.
Your server for instance, had about the same number of lines of code as my solution had (mine is not perfect i know), but i managed to squeeze in threading and if i/you wnated to also a "friendslist"..
Take good use of loops, functions and stuff.. They'll save your life :)
Also note
That if you intend to use the socket as a client, you don't need to do s.bind(()) or s.listen(5), that's server-side properties.

Related

socket chat room - python 3.7

This is a python chat room that I've been working on and it enables to you to chat to other people on the same network through python
Host:
import socket
import sys
import time
s = socket.socket()
host = socket.gethostname()
port = 8080
s.bind((host,port))
print("")
print("Sever adress is", host)
print("")
name = input(str("Please enter your username : "))
s.listen(1)
print("")
print("Waiting for any incoming connections ... ")
print("")
conn, addr = s.accept()
print("Recieved connection")
#connection done ###
s_name = conn.recv(1024)
s_name = s_name.decode()
print("")
print(s_name, "has connected to the chat room")
print("")
conn.send(name.encode())
## messaging loop ##
while 1:
message = input(str("Please enter enter your message : "))
print("")
conn.send(message.encode())
message = conn.recv(1024)
message = message.decode()
print("")
print(name,": ",message)
print("")
Client:
import socket
import sys
import time
print("Welcome to python chat ")
print("")
print("Initiallsing....")
time.sleep(1)
s = socket.socket()
print("")
host = input(str("Please enter server adress : "))
print("")
name = input(str("Please enter your name : "))
port = 8080
print("")
time.sleep(1)
s.connect((host,port))
print("Connected...")
## Conection done ##
s.send(name.encode())
s_name = s.recv(1024)
s_name = s_name.decode()
print("")
print( s_name, "has joined the chat room ")
while 1:
message = s.recv(1024)
message = message.decode()
print("")
print(name,": ",message)
print("")
message = input(str("Please enter your enter message : "))
print("")
s.send(message.encode())
I have 2 problems, the first problem is that it only allows one person to speak at a time, what I mean by this say that if you send a message first you won't be allowed to send another message until the other person has responded. The second problem is that this code only works for 2 users, I want it so it works for multiple users
Edit:
Also could some one acutually give a proper solution instead of telling me to start all over again please because it took me so long to figure out how to make this system in the place.
Thank you
You need to create two separate threads for sending and receiving. The way you have written the loop will not work for both way communication simultaneously. Because after sending a message the loop is waiting to receive something. [If you want to run the code over internet, replace localhost with the desired IP address in the line HOST = 'localhost'] Let me share a solution (this is a sample solution I have done while TAing an undergraduate class on networking):
I have tested the code on a Linux machine (Ubuntu 18.04). I have got students who have successfully ran this on their Mac. I am not sure if it runs on a windows machine. Even if it does not work on a Windows machine, a few minor modifications should do the trick.
Server sider code (you need to run this first): chatServerDuplex.py
# Import socket module
from socket import *
import threading
import sys # In order to terminate the program
FLAG = False # this is a flag variable for checking quit
# function for receiving message from client
def recv_from_client(conn):
global FLAG
try:
# Receives the request message from the client
while True:
if FLAG == True:
break
message = conn.recv(1024).decode()
# if 'q' is received from the client the server quits
if message == 'q':
conn.send('q'.encode())
print('Closing connection')
conn.close()
FLAG = True
break
print('Client: ' + message)
except:
conn.close()
# function for receiving message from client
def send_to_client(conn):
global FLAG
try:
while True:
if FLAG == True:
break
send_msg = input('')
# the server can provide 'q' as an input if it wish to quit
if send_msg == 'q':
conn.send('q'.encode())
print('Closing connection')
conn.close()
FLAG = True
break
conn.send(send_msg.encode())
except:
conn.close()
# this is main function
def main():
threads = []
global FLAG
# TODO (1) - define HOST name, this would be an IP address or 'localhost' (1 line)
HOST = 'localhost'
# TODO (2) - define PORT number (1 line) (Google, what should be a valid port number)
# make sure the ports are not used for any other application
serverPort = 6789
# Create a TCP server socket
#(AF_INET is used for IPv4 protocols)
#(SOCK_STREAM is used for TCP)
# TODO (3) - CREATE a socket for IPv4 TCP connection (1 line)
serverSocket = socket(AF_INET, SOCK_STREAM)
# Bind the socket to server address and server port
# TODO (4) - bind the socket for HOSR and serverPort (1 line)
serverSocket.bind((HOST, serverPort))
# Listen to at most 1 connection at a time
# TODO (5) - listen and wait for request from client (1 line)
serverSocket.listen(1)
# Server should be up and running and listening to the incoming connections
print('The chat server is ready to connect to a chat client')
# TODO (6) - accept any connection request from a client (1 line)
connectionSocket, addr = serverSocket.accept()
print('Sever is connected with a chat client\n')
t_rcv = threading.Thread(target=recv_from_client, args=(connectionSocket,))
t_send = threading.Thread(target=send_to_client, args=(connectionSocket,))
# call the function to receive message server
#recv_from_server(clientSocket)
threads.append(t_rcv)
threads.append(t_send)
t_rcv.start()
t_send.start()
t_rcv.join()
t_send.join()
# closing serverScoket before exiting
print('EXITING')
serverSocket.close()
#Terminate the program after sending the corresponding data
sys.exit()
# This is where the program starts
if __name__ == '__main__':
main()
Client side code: chatClientDuplex.py
from socket import *
import threading
import sys
FLAG = False # this is a flag variable for checking quit
# function for receiving message from client
def send_to_server(clsock):
global FLAG
while True:
if FLAG == True:
break
send_msg = input('')
clsock.sendall(send_msg.encode())
# function for receiving message from server
def recv_from_server(clsock):
global FLAG
while True:
data = clsock.recv(1024).decode()
if data == 'q':
print('Closing connection')
FLAG = True
break
print('Server: ' + data)
# this is main function
def main():
threads = []
# TODO (1) - define HOST name, this would be an IP address or 'localhost' (1 line)
HOST = 'localhost' # The server's hostname or IP address
# TODO (2) - define PORT number (1 line) (Google, what should be a valid port number)
PORT = 6789 # The port used by the server
# Create a TCP client socket
#(AF_INET is used for IPv4 protocols)
#(SOCK_STREAM is used for TCP)
# TODO (3) - CREATE a socket for IPv4 TCP connection (1 line)
clientSocket = socket(AF_INET, SOCK_STREAM)
# request to connect sent to server defined by HOST and PORT
# TODO (4) - request a connection to the server (1 line)
clientSocket.connect((HOST, PORT))
print('Client is connected to a chat sever!\n')
# call the function to send message to server
#send_to_server(clientSocket)
t_send = threading.Thread(target=send_to_server, args=(clientSocket,))
# call the function to receive message server
#recv_from_server(clientSocket)
t_rcv = threading.Thread(target=recv_from_server, args=(clientSocket,))
threads.append(t_send)
threads.append(t_rcv)
t_send.start()
t_rcv.start()
t_send.join()
t_rcv.join()
print('EXITING')
sys.exit()
# This is where the program starts
if __name__ == '__main__':
main()
Your first problem is likely due to the fact that python sockets are blocking by default.
What this means is that, for example, on the line message = s.recv(1024), your program will keep listening and won't move on to the rest of your script until it receives something.
If you want two people to be able to receive and send at the same time, you might want to look into non-blocking sockets and some asynchronous programming.
This how-to from the official documentation might help you: https://docs.python.org/2/howto/sockets.html#non-blocking-sockets
System123456 the problem is that you built a client-server system when the server listens and the client connects to it. Try looking at peer-to-peer systems instead where each node is an equal. For building a chat room you might review DHT nodes.

The server is behaving as if it is blocked but i have set it to non blocking

The server only listens for a message from the first socket to connect, even though it is set to nonblocking, it doesn't skip over it when it doesn't receive data. I'm new to networking and this is my first project, if anyone know of any others good for beginners please let me know. Thanks! Here is the code.
import socket
CONNECTED_SENDERS = []
CONNECTED_LISTENERS = []
def Main():
HOST = socket.gethostname()
PORT = 4444
SERVER_SOCKET = socket.socket()
SERVER_SOCKET.bind((HOST, PORT))
SERVER_SOCKET.listen(1)
for i in range(2):
CONNECTION, ADDRESS = SERVER_SOCKET.accept()
CONNECTED_LISTENERS.append(CONNECTION)
for i in range(2):
CONNECTION, ADDRESS = SERVER_SOCKET.accept()
CONNECTED_SENDERS.append(CONNECTION)
for DEVICE in CONNECTED_LISTENERS:
DEVICE.send(b'SERVER: You have succesfully connected.')
DEVICE.send(b'SERVER: Please wait for permission to talk.')
x = 0
for DEVICE in CONNECTED_LISTENERS:
DEVICE.send(b'SERVER: What is your name?')
Name = CONNECTED_SENDERS[x].recv(1024)
CONNECTED_LISTENERS[x] = (CONNECTED_LISTENERS[x], Name)
x += 1
del x, Name
for DEVICE, _ in CONNECTED_LISTENERS:
DEVICE.send(b'SERVER: You may now talk.')
SERVER_SOCKET.setblocking(0)
LEAVE = False
while LEAVE == False:
try:
MESSAGE = CONNECTED_SENDERS[0].recv(1024)
NAME = CONNECTED_LISTENERS[0][1]
for DEVICE, _ in CONNECTED_LISTENERS:
DEVICE.send(NAME + b': ' + MESSAGE)
if MESSAGE == 'QUIT':
LEAVE = True
except:
try:
MESSAGE = CONNECTED_SENDERS[1].recv(1024)
NAME = CONNECTED_LISTENERS[1][1]
for DEVICE, _ in CONNECTED_LISTENERS:
DEVICE.send(NAME + b': ' + MESSAGE)
if MESSAGE == 'QUIT':
LEAVE = True
except:
pass
for CONNECTION in CONNECTED_LISTENERS:
CONNECTION.close()
for CONNECTION in CONNECTED_SENDERS:
CONNECTION.close()
if __name__ == "__main__":
Main()
There are a number of issues with your code, some small and some big. But the main problem is that you're marking the server socket nonblocking, not any of the sockets on which communication takes place.
In standard TCP socket programming, you set up a server which listens for incoming connections. When that server accepts a new client, this returns a new socket, and it's on this new socket that all communication with the remote client happens. In other words, the server socket is just for accepting new connections, and nothing else. You never write data through the server socket.
So it doesn't matter that SERVER_SOCKET is marked nonblocking, you must do something like this:
conn, addr = server.accept()
conn.setblocking(False)
conn is the new socket through which you talk to the client, and can be used in a nonblocking fashion.
Smaller issues:
I should also point out that you call SERVER_SOCKET.listen(1). That argument of 1 means that the server will only have a backlog of waiting connections from one client. So if a second client connects before the first connection is made, the second client will receive an error, ECONNREFUSED. Given what it looks like you're trying to do, I'd guess SERVER_SOCKET.listen(4) is appropriate.
Next, nonblocking communication is much harder than blocking protocols. I'd suggest you improve your networking skills before tackling them, but when you're ready, look at the select or selectors modules for help. They provide tools to wait for communication from any of a number of clients, rather than looping over them all and checking if data is available, as you've done here. This looping is very inefficient.
Finally, in Python, it's good practice to name variables with lower case, underscore-separated names. UPPER_CASE_NAMES are usually reserved for constants. So change SERVER_SOCKET to server_socket, CONNECTED_LISTENERS to connected_listeners, etc.

Send messages received by server to multiple clients in python 2.7 with socket programming

So I have created a socket program for both client and server as a basic chat. I made it so the server accepts multiple clients with threading, so that is not the problem. I am having trouble sending messages to each client that is connected to the server. I am not trying to have the server send a message it created but rather have client1 sending a message to client2 by going through the server. For some reason it will only send it back to client1.
For example, client1 will say hello and the server will send the same message back to client1 but nothing to client2. I fixed this slightly by making sure the client doesn't receive its own message but client2 is still not receiving the message from the client1.
Any help will be appreciated.
I have tried multiple changes and nothing seems to work. You can look at my code for specifics on how I did things but ask if there are any questions.
Also, there is a question where someone has asked that is similar and I thought it would give me an answer but the responses stopped going through and a solution was never fully given, so please don't just refer me to that question. that is located here: Python 3: Socket server send to multiple clients with sendto() function.
Here's the code:
CLIENT:
import socket
import sys
import thread
#Create a socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Enter username to identify self to others
name = raw_input("Enter username: ") + ": "
#Connect socket to ip and port
host = socket.gethostname()
#host = '192.168.1.10'
server_address = (host, 4441)
sock.connect(server_address)
#function waiting to receive and print a message
def receive(nothing):
while True:
data = sock.recv(1024)
if message != data:
print data
# Send messages
while True:
#arbitrary variable allowing us to have a thread
nothing = (0, 1)
message = name + raw_input("> ")
sock.sendall(message)
#thread to receive a message
thread.start_new_thread(receive, (nothing,))
SERVER:
import socket
import sys
import thread
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
host = socket.gethostname()
server_address = (host, 4441)
sock.bind(server_address)
#Listen for incoming connections
sock.listen(5)
print "Waiting for connection..."
#Variable for the number of connections
numbOfConn = 0
#Name of list used for connections
addressList = []
#Function that continuosly searches for connections
def clients(connection, addressList):
while True:
message = connection.recv(1024)
print message
#connection.sendall(message)
#for loop to send message to each
for i in range(0,numbOfConn - 1):
connection.sendto(message, addressList[i])
connection.close()
while True:
#accept a connection
connection, address = sock.accept()
print 'Got connection from', address
numbOfConn += 1
addressList.append((address))
#Thread that calls the function: clients and stores them in a tuple called connection
thread.start_new_thread(clients, (connection, addressList))
sock.close()
Please help me if you can!
EDIT:
I was able to fix it to a certain extent. It is still a little buggy but I am able to send messages back and forth now. I needed to specify the connection socket as well as the address. Here's the updated code:
SERVER
import socket
import sys
import thread
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
host = socket.gethostname()
server_address = (host, 4441)
sock.bind(server_address)
#Listen for incoming connections
sock.listen(5)
print "Waiting for connection..."
#Variable for the number of connections
numbOfConn = 0
#Name of list used for connections
addressList = []
connectionList = []
#Function that continuosly searches for connections
def clients(connectionList, addressList):
while True:
for j in range(0,numbOfConn):
message = connectionList[j].recv(1024)
print message
#for loop to send message to each
for i in range(0,numbOfConn):
connectionList[i].sendto(message, addressList[i])
connection.close()
while True:
#accept a connection
connection, address = sock.accept()
print 'Got connection from', address
numbOfConn += 1
addressList.append((address))
connectionList.append((connection))
#Thread that calls the function: clients and stores them in a tuple called connection
thread.start_new_thread(clients, (connectionList, addressList))
sock.close()

Threading - How to recieve and reply at the same time using the socket module?

I am trying to make a simple LAN instant messager where many clients connect to the server and the server replies back and can see what the client is saying. I have tried but my lack of knowledge using the threading module has limited me. At the moment, however, the server only gets a message and has to reply to get the next one. I am trying to make it so the server can see all the messages it receives instantly and can reply whenever he need to. How?
Server Code:
from threading import *
import socket
s = socket.socket()
host = socket.gethostbyname(socket.gethostname())
port = 1337
s.bind((host, port))
s.listen(5)
def getMainThread():
for thread in enumerate(): # Imported from threading
if thread.name == 'MainThread':
return thread
if thread.name == 'Thread':
return thread
return None
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.socket = socket
self.address = address
self.start() # Initated the thread, this calls run()
def reply(self):
reply = getThread()
while reply and reply.isAlive():
sent = input("Enter Message: ")
self.socket.send(bytes(sent, 'UTF-8'))
def run(self):
main = getMainThread()
while main and main.isAlive():
message = self.socket.recv(8192).decode('utf-8')
self.socket.send(b"Got your message.. send another one!")
print('Someone:',message)
sent = input("Enter Message: ")
self.socket.send(bytes(sent, 'UTF-8'))
self.socket.close()
while True:
c, addr = s.accept()
client(c, addr)
Client Code:
import socket
host = socket.gethostbyname(socket.gethostname())
print("""
================================================================================
Welcome to Coder77's local internet message for avoiding surveillance by the NSA
================================================================================
The current soon to be encrypted server is {0}
""".format(host))
#host = input("Please select the IP you would like to communicate to: ")
print("Now connecting to {0}....".format(host))
sock = socket.socket()
try:
sock.connect((host, 1337))
while True:
message = input("Enter Message: ")
if message == 'quit':
break
sock.send(bytes(message, 'UTF-8'))
recieved = sock.recv(8192).decode('utf-8')
print('Server responded with:', recieved)
except socket.error:
print ("Host is unreachable")
sock.close()
Also, is it possible using Threading so that 2 while statements can run at the same time? If so, can someone give me an example?
Boosting this to try and get an answer. Anyone?

Python: Notification System?

I am working on a chat server that runs on my local network using socket, and then I have a client program running on all of the computers in my house, and this program allows all of the clients to talk to each other.
The problem is, you have to manually update the chat log by pressing enter.
The way I want it to work, maybe, is to check for a new message every few seconds, and if there is a new one, play a sound. Does anyone know how I can do this, I'll try to figure it out on my own, as I have done with most of this project, but any help is appreciated.
Here is the server:
import socket
import sys
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('192.168.1.80', 10000)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)
sock.listen(1)
print 'Waiting for user...'
convo='Welcome!'
while True:
# Find connections
connection, client_address = sock.accept()
try:
data = connection.recv(999)
if data=='EMPTY':
pass
else:
print data
convo=convo+'\n'+data
connection.sendall(convo)
except:
connection.close()
Here is the client:
import socket
import sys,os
name=raw_input("Enter name: ")
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('192.168.1.80', 10000)
print >>sys.stderr, 'connecting to %s port %s' % server_address
while True:
message=raw_input('Message: ')
try:
os.system('cls')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(server_address)
if message is not '':
sock.sendall(name+": "+message)
else:
sock.sendall('EMPTY')
if message=='quit':
break
x=sock.recv(999)
print x
except:
break
sock.close()
Thanks!
If you need two operations to happen at the same time (the client script needs to read input from the user and read new messages from the server), then you'd need to either use threads (one thread for reading user input, and one for reading messages from the server), or futures (since python3.2).
Here's question for playing audio in python: Play audio with Python
As for your client, why are you reconnecting to your server every single time? Anyway, if I understand the problem correctly you're blocking on user input, but also want to handle messages from the server.
Without getting complicated with threads, I would recommended using a recurring signal, which I believe could handle this. There's a function call setitimer(), which will break what you're doing and call a function every so often then return to where you were (user input). In your timer function, check for server messages, print any received, play your sound and return to user input. There's an setitimer() example enter link description here.
Might be a little ugly with the user typing, so you may need to reprint what they're currently typing, but haven't sent out (using something other than raw_input()).
For a slightly more complicated option, which may help you there's a function call select(), which can block while listening for socket input AND user input. Then you just distinguish which is which and keep it all in one loop.
while True:
# select on server socket and user input (blocks for either one)
# if here, either a message has been received or the user typed something
# if a message from server
...
playSound()
# else
# send to server

Categories

Resources