After that I have connected to the server from input, how do I change my server in the chat?
I just updated the code with something that could work though it needs some more work, anyone?
def send(event=None): # event is passed by binders.
"""Handles sending of messages."""
global HOST
global PORT
global ADDR
msg = my_msg.get()
my_msg.set("") # Clears input field.
msg_list1 = msg.split()
try:
if msg_list1 [0] == "/connect":
try:
HOST = msg_list1[1]
PORT = int(msg_list1[2])
ADDR = (HOST,PORT)
client_socket.connect(ADDR)
receive_thread = Thread(target=receive)
receive_thread.start()
except TypeError:
msg_list_tk.insert(tt.END, "Error: please write '/connect ADDR PORT' to connect to server\n")
if msg_list1 [0] == "/connectnew":
HOST = msg_list1[1]
PORT = int(msg_list1[2])
ADDR = (HOST,PORT)
client_socket_2.connect(ADDR)
receive_thread = Thread(target=receive)
receive_thread.start()
except:
msg_list_tk.insert(tt.END, "Error: please write '/connect ADDR PORT' to connect to server\n")
elif msg == "/q":
root.quit()
client_socket.send(b"/q")
elif msg == "/disconnect":
client_socket.close()
else:
client_socket.send(bytes(msg, "utf8"))
except:
msg_list_tk.insert(tt.END, "Wrong input\n")
A TCP socket is only usable for a single TCP connection. If you want a second connection, you need to create a new socket and call connect() on that (i.e. you can't call connect() on your old socket a second time).
Related
Hi This is my first post here. I am making a chatroom in Python using sockets and I have written the code for the server and client side. I am successful in establishing a connection between the server and the clients but I can't send any messages. The client provides a password and username through terminal and the server check if the password is correct and only then the client can send messages. I have not yet implemented the password check yet but the messages are still not being sent. I have made sure I am encoding and decoding correctly. I have also implemented threading to allow multiple users. Here is the server side code:
import socket
import threading
import sys
#TODO: Implement all code for your server here
#usernames = []
def broadcast(message):
for client in clients:
client.send(message)
def handle_client(client_socket, client_address):
try:
password = client_socket.recv(1024).decode()
username = client_socket.recv(1024).decode()
print("user: " + username)
clients.append(client_socket)
while True:
message = username + " joined the chatroom"
print(message)
broadcast(message.encode())
message = client_socket.recv(1024).decode()
if (message != ":Exit"):
print(f"{username}: {message}")
broadcast(message.encode())
else:
print(f"{username} left the chatroom")
clients.remove(client_socket)
client_socket.close()
message = username + " left the chatroom"
broadcast(message.encode())
break
except:
client_socket.close()
def receive():
while True:
client_socket, client_address = server.accept()
print(client_socket)
client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address))
client_thread.start()
# Use sys.stdout.flush() after print statemtents
if __name__ == "__main__":
HOST = '127.0.0.1'
#PORT = int(sys.argv[1])
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, 10001))
server.listen(5)
clients = []
print("server is listening")
receive()
Here is the client side:
import socket
import threading
import sys
#TODO: Implement a client that connects to your server to chat with other clients here
HOST = '127.0.0.1'
#PORT = int(sys.argv[1])
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, 10001))
username = sys.argv[1]
password = sys.argv[2]
client_socket.send(password.encode())
client_socket.send(username.encode())
reply = client_socket.recv(1024).decode()
print(reply)
def receive():
while True:
try:
message = client_socket.recv(1024).decode()
if message:
print(message)
except:
continue
def write():
while True:
message = input()
if message == ":Exit":
client_socket.send(message.encode())
client_socket.close()
break
else:
client_socket.send(message.encode())
receive_thread = threading.Thread(target=receive)
receive_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
# Use sys.stdout.flush() after print statemtents
if __name__ == "__main__":
pass
I have tried asking my TAs but they were of no help :(.
It looks like you are taking the second and third arguments instead of first and second. Thus if you do not pass 3 arguments with the third being the password then the client will not have a password to send.
I wanted to create a server-client chatbox room in python, where multiple clients could send messages in the chat box.
This is the server code
import threading
import socket
#setting up the local host and the local port
host = '127.0.0.1'
port = 9879
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port)) #hosting the server to the host
server.listen() #server listen to incoming connection
#list for client and their nicknames
clients = []
nicknames = []
#broadcast method to send message to all the clients connected to the server
def broadcast(message):
for client in clients:
client.send(message)
def handle (client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except: #if the connection is lost, discard the client
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
broadcast(f'{nickname} already left the chat!'.encode('ascii'))
nicknames.remove(nickname)
break
#function to receive connection
def receive():
while True:
client, address = server.accept()
print(f"Conncected with {str(address)}")
client.send('NICKNAME'.encode('ascii'))
nickname = client.recv(1024).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f'The nickname of the client is {nickname}')
broadcast(f'{nickname} joined the chat!'.encode('ascii'))
client.send('Connected to the server!'.encode('ascii'))
#making thread for every client
thread = threading.Thread(target = handle, args = (client,))
thread.start()
print("Server is waiting for client...")
and this is the client code
import socket
import threading
#nickname prompt
nickname = input("Input your nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#binding the client to the port
client.connect(('127.0.0.1', 9879))
def receive():
while True:
try:
message = client.recv(1024).decode('ascii')
if message == 'NICKNAME':
client.send(nickname.encode('ascii'))
else:
print(message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f'{nickname}: {input("")}'
client.send(message.encode('ascii'))
#making the thread
receive_thread = threading.Thread(target = receive)
receive_thread.start()
write_thread = threading.Thread(target = write)
write_thread.start()
However, whenever i inputted the nickname in the command prompt there was an error
Traceback (most recent call last):
File "C:\Users\march\Documents\Programming\Pyhton\client.py", line 8, in <module>
client.connect(('127.0.0.1', 9879))
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
I wonder what's the problem because the port for both server and client are the same and the port is available.
On your server code you're missing a call to the receive function that runs the while loop and puts the server on accept for connections.
The code becomes
import threading
import socket
#setting up the local host and the local port
host = '127.0.0.1'
port = 9879
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port)) #hosting the server to the host
server.listen() #server listen to incoming connection
#list for client and their nicknames
clients = []
nicknames = []
#broadcast method to send message to all the clients connected to the server
def broadcast(message):
for client in clients:
client.send(message)
def handle (client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except: #if the connection is lost, discard the client
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
broadcast(f'{nickname} already left the chat!'.encode('ascii'))
nicknames.remove(nickname)
break
#function to receive connection
def receive():
while True:
client, address = server.accept()
print(f"Conncected with {str(address)}")
client.send('NICKNAME'.encode('ascii'))
nickname = client.recv(1024).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f'The nickname of the client is {nickname}')
broadcast(f'{nickname} joined the chat!'.encode('ascii'))
client.send('Connected to the server!'.encode('ascii'))
#making thread for every client
thread = threading.Thread(target = handle, args = (client,))
thread.start()
print("Server is waiting for client...")
receive() # runs the function that accepts for incoming connections
The client code should run the write() function on the main thread and not on another one, because it requires input from the stdin. You can change your code as follows in order to run the receiving routine on another thread and your "writing" function on the main one.
import socket
import threading
#nickname prompt
nickname = input("Input your nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#binding the client to the port
client.connect(('127.0.0.1', 9879))
def receive():
while True:
try:
message = client.recv(1024).decode('ascii')
if message == 'NICKNAME':
client.send(nickname.encode('ascii'))
else:
print(message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f'{nickname}: {input("")}'
client.send(message.encode('ascii'))
#making the thread
receive_thread = threading.Thread(target = receive)
receive_thread.start()
# on the main thread
write()
The cause of the Connection refused error was due to the fact that the server code immediately exited since the receive function was never actually called.
Problem while making connection with server.
server side:
import socket
import threading
import sys
ip = "let ip address of server, cant type real one for security purposes, example: 1.2.3.4"
port = 9999
def make_socket(ip, port):
global server
try:
server = socket.socket()
server.bind((ip, port))
except:
make_socket(ip, port)
def handle_client(conn, addr):
print(f"Connected with {addr}\n")
connected = True
while connected:
msg = conn.recv(1024).decode("utf-8")
if msg == "exit()":
connected = False
if len(msg) > 0:
print(f"CLIENT: {msg}")
if connected:
msg = input("You: ")
if len(msg) > 0:
conn.send(msg.encode("utf-8"))
conn.close()
def make_connection():
server.listen(2)
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"ACTIVE CONNECTIONS:{threading.activeCount() - 1}")
print("SERVER INITIATED.")
make_socket(ip, port)
make_connection()
client side:
import socket
ip = "same address as written in server side, example: 1.2.3.4"
port = 9999
client = socket.socket()
client.connect((ip, port))
def send(msg):
message = msg.encode("utf-8")
client.send(message)
run = True
while run:
msg = input("You: ")
if msg == "exit()":
send(msg)
run = False
else:
send(msg)
print(f"Server: {client.recv(100).decode('utf-8')}")
It runs as expected in the same pc.
But when I am running client script and server script in 2 different pcs, they are not connecting. Even though the address is same. I have to type the ip address of server in server.bind and client.connect, right? They both should be same, right?
The IP address you pass to client.connect() should be the IP address of the computer where the server is running (if it's the same computer as where the client is running, you can just pass 127.0.0.1 as that address always means localhost). For the bind() call I recommend passing in '' (i.e. an empty string) as the address, so that your server will accept incoming connections from any active network interface. You only need to pass in an explicit IP address to bind() if you want limit incoming connections to only those coming through the local network card that is associated with the specified IP address.
I am currently using the socket library in python to send basic text from one computer to another on the same local network.
My problem is that due to me using different computers on multiple occasions the iPv4 which the client connects to changes each time .
Line 4 of the client code : client.connect(("172.16.0.34",8888))
This introduces a difficulty as I cant change the ip in the client code very easily.
My Question:
Is there possibly a way that the client can "scan" the network to see what ip is hosting a socket and obtain that ip to connect to them, allowing me to use any computer and have it still functioning?
Here is my code:
Client:
import socket
client = socket.socket()
try:
client.connect(("172.16.0.34",8888))
except:
print("Server not connected")
else:
print("Connect to server: ","localhost")
while True:
print("[Waiting for response...]")
print(client.recv(1024))
valid = False
while not valid:
try:
msg = str(input("Enter your message to send: "))
except:
print("Invalid input format")
else:
valid = True
to_send = msg.encode("UTF-8")
client.send(to_send)
Server:
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created")
host = "0.0.0.0"
port = 8888
print(host)
try:
server.bind((host,port))
except:
print("Bind failed")
else:
print("Bind successful")
server.listen(5)
clientsocket = None
while True:
if clientsocket == None:
print("[Waiting for connection..]")
(clientsocket, address) = server.accept()
print("Client accepted from", address)
else:
print("[Waiting for response...]")
print(clientsocket.recv(1024))
valid = False
while not valid:
try:
msg = str(input("Enter your message to send: "))
except:
print("Invalid input format")
else:
valid = True
clientsocket.send(msg.encode("UTF-8"))
I am trying to send and receive data using TCP connection using Python. My server and client are in the same file, defined and used as follows.
In the constructor, I define the server as:
self.sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock_in.bind((self.host_ip, self.host_port))
self.sock_in.listen(1)
Do not worry about the host_ip and host_port variables, they are all fine.
In a function, I am trying to send data as follows:
sock_out = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP Connection
sock_out.connect((self.remote_ip, self.remote_port))
sock_out.send(self.navigation_data.get_message())
sock_out.close()
And this is my main:
def main(self):
rospy.logwarn("Starting...")
while not rospy.is_shutdown():
conn = self.sock_in.accept()
try:
recv_buffer = conn.recv(BUFFERSIZE_IN)
if recv_buffer != "":
msg = recv_buffer.decode('utf-8')
msg_type = msg[:msg.find(',')]
if msg_type == self.pilot_control.MESSAGE_ID:
self.pilot_control_handler(msg, self.pilot_control_publisher)
else:
rospy.logwarn("Received an unimplemented message type '%s'", msg_type)
except socket.error as socket_error:
rospy.logerr("SocketError: %s", str(socket_error))
And the error I get is:
line 230, in send_83b_package
sock_out.connect((self.remote_ip, self.remote_port))
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
error: [Errno 111] Connection refused
I put some print commands to see where it collapses, and apparently it does not run the accept command. Until there I can see the print commands working, but after the accept method nothing is printed, which means it collapses there.
I suspect the problem is about synchronization. That is, the server does not start fast enough.
Any thoughts?
EDIT:
One of the suggestions was to run the server on a separate thread, which I tried as follows:
def my_tcp_server(self):
# Establish a TCP Connection
self.sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock_in.bind((self.host_ip, self.host_port))
self.sock_in.listen(1)
rospy.logwarn("ready")
while not rospy.is_shutdown():
rospy.logwarn("before accept")
conn, address = self.sock_in.accept()
rospy.logwarn("after accept")
try:
recv_buffer = conn.recv(BUFFERSIZE_IN)
rospy.logwarn("recv works!")
if recv_buffer != "":
msg = recv_buffer.decode('utf-8')
msg_type = msg[:msg.find(',')]
if msg_type == self.pilot_control.MESSAGE_ID:
self.pilot_control_handler(msg, self.pilot_control_publisher)
else:
rospy.logwarn("Received an unimplemented message type '%s'", msg_type)
except socket.error as socket_error:
rospy.logerr("SocketError: %s", str(socket_error))
conn.close()
def main(self):
rospy.logwarn("Starting..")
threading.Thread(target=self.my_tcp_server).start()
And in my constructor, the order of calls are as follows:
self.main()
self.sendDataFunction()
Which should be okay. However, the accept function is still not working, hence there is no connection.
As you didn't provide a complete executable code example I took your snippet and removed the class declaration aspects, added definitions for ip/port etc. Also added socket timeout. Anywayt this code works for me on Windows 7x64 with 32-bit Python 2.7.8:
import threading
import socket
is_shutdown = False
BUFFERSIZE_IN = 32768
def my_tcp_server():
# Establish a TCP Connection
sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_in.bind((host_ip, host_port))
sock_in.settimeout(10000)
sock_in.listen(1)
print "ready"
while not is_shutdown:
print "before accept"
conn, address = sock_in.accept()
print "after accept"
try:
recv_buffer = conn.recv(BUFFERSIZE_IN)
print "recv works!"
if recv_buffer != "":
msg = recv_buffer.decode('utf-8')
print "Received",msg
except socket.error as socket_error:
print "SocketError: %s", str(socket_error)
conn.close()
print "Shutting down server"
sock_in.close()
def main():
print "Starting.."
threading.Thread(target=my_tcp_server).start()
def sendData():
sock_out = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP Connection
sock_out.connect((remote_ip, remote_port))
sock_out.send("ASD")
sock_out.close()
host_ip="127.0.0.1"
remote_ip = host_ip
host_port = 8073
remote_port = host_port
main()
print "Sending"
sendData()
print "Completed"
is_shutdown = True
The output is:
Starting..
Sending
ready
before accept
Completedafter accept
recv works!
Received ASD
Shutting down server
I guess there is something in your class/constructor/something I can't see which is making your code not work.
HTH
barny