Please help me in socket programming in python - python

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.

Related

Python socket server can only receive one message from client

I am currently developping a chat program, and I have a problem.
The server can only receive one information from the client and then stop receiving information.
here's my code :
Server.py
import socket
import threading
# Some base important value
ip = '0.0.0.0'
port = 25565
encoding = 'utf-8'
# Some runtime value
clientList = []
is_server_running = True
# a class representing a client
class ClientThread(threading.Thread):
conn = None
addr = None
# Use to init the thread and the main client value
def __init__(self, conn, addr):
threading.Thread.__init__(self)
self.conn = conn
self.addr = addr
print(f"Successfully created client thread for client {self.addr[0]}:{self.addr[1]}")
# Use to receive and send data
def run(self):
while True:
try:
data = self.conn.recv(1024).decode(encoding)
print(f"Got message from client ({self.addr[0]}:{self.addr[1]}) : \"{data}\"")
except Exception as e:
print(f"Got exception in client {self.addr[0]}:{self.addr[1]} : {str(e)}")
break
clientList.remove(self)
# Create a socket and bind the correct port and ip
print("Creating Server...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((ip, port))
s.listen(5)
print(f"Server created and launched on port {port}.")
while is_server_running:
try:
# Accept the connection and create a new client thread
conn, adrr = s.accept()
print(f"Got new connection from adress {adrr[0]}:{adrr[1]}. Creating Thread for client")
client_thread = ClientThread(conn, adrr)
client_thread.start()
clientList.append(client_thread)
except Exception as e:
print(f"Got Exception in server listening runtime : {str(e)}. Server Stopped")
is_server_running = False
break
for client in clientList:
client.conn.close()
s.close()
Client.py
import socket
# base important variables
encoding = 'utf-8'
adress = 'here is the server ip'
port = 25565
# runtime variables
is_client_running = True
# Create a socket and connects to the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((adress, port))
message = "Hello !".encode(encoding)
s.sendall(message)
while is_client_running:
message = input(">>> ")
s.sendall(message.encode(encoding))
Output :
Creating Server...
Server created and launched on port 25565.
Got new connection from adress -----------:----. Creating Thread for client
Successfully created client thread for client -----------:----
Got message from client (-----------:----) : "Hello !"
And then when I input something in the client console (like : Goodbye), the server receive nothing.
Thank you for your help !

ConnectionRefusedError is raised when trying to run a program

I built a chat room with python so that I can talk to my friends a different way but for some reason, my friend is getting a ConnectionRefusedError. I have a server.py file and a client.py file. The client.py files are the exact same, however my friend is the only one getting the error but not me. I don't know where I'm making a mistake so here's the code for both files:
server.py
import threading
import socket
host = "127.0.0.1" #localhost
port = 48812
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen()
clients = []
nicknames = []
def broadcast(message):
for client in clients:
client.send(message)
def handle(client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except:
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
broadcast(f"{nickname} left the chat".encode('ascii'))
nicknames.remove(nickname)
break
def receive():
while True:
client, address = server.accept()
print(f"Connected with{str(address)}")
client.send("NICK".encode("ascii"))
nickname = client.recv(1024).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f"Nickname of client is {nickname}\n")
broadcast(f'{nickname}joined the chat!\n'.encode('ascii'))
client.send("Connected to the server!\n".encode('ascii'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
print("Server is listening...")
receive()
client.py
import socket
import threading
nickname = input("Choose a nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 48812))
def receive():
while True:
try:
message = client.recv(1024).decode('ascii')
if message == 'NICK':
pass
else:
print(message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f'{nickname}: {input("")}'
client.send(message.encode('ascii'))
receive_thread = threading.Thread(target=receive)
receive_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
We were connected to the same wifi so I thought that it should work. Does anyone know how to fix this?
The IP-address 127.0.0.1 is the localhost (or "loopback" address), which is the address to your own computer. With it you can run the server and client on the same computer, but you can't connect to the server from a different computer.
Even though you're on the same WiFi, you still have different IP-addresses. Each device that connects to the internet needs an IP-address that doesn't conflict with other addresses. Basically, a router is connected to the "big" internet with a public IP-address and can talk with other devices around the world. Then you have a "small" internet on your side of the router where your computer, phone, smart-TV, etc. is connected. These all have private addresses, i.e. addresses that are only unique within the network of the router.
For your server to work, it needs to listen to all IP-addresses (or the client's private IP-address, which most likely is something like 192.168.1.X where X is some number). You can listen to all addresses by binding to 0.0.0.0
For your client to work, you need to connect to the server's private IP-address.
How to find it depends on your OS, but it's usually in the system settings or preferences. If you have Mac OS, then you can click on the WiFi icon while holding down the alt-key.

Is there a way to run a python chat server from my computer so the clients can join from their computers via another network?

I wrote a chat server with python and socket. Clients can connect to it via the local network but i need the clients to be able to connect to the server from another networks. I tried using 0.0.0.0 for the host IP in the server and I got this error message when trying to connect to it via another network
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
This is my code for the server
import threading
import socket
host = "0.0.0.0"
port = 55555
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen()
clients = []
usernames = []
print("Server is online and running......")
def broadcast(message):
for client in clients:
client.send(message)
def handle(client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except:
index = clients.index(client)
clients.remove(client)
client.close()
user = usernames[index]
broadcast(f"{user} left the chat!".encode("ascii"))
usernames.remove(user)
break
def receive():
while True:
client, address = server.accept()
print(f"Connected With {str(address)}")
client.send("NICK".encode("ascii"))
username = client.recv(1024).decode("ascii")
usernames.append(username)
clients.append(client)
print(f"Username - {username}")
broadcast(f"{username} just Joined the chat!".encode("ascii"))
client.send("connected to the server!".encode("ascii"))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
receive()
And this is the code for the client
import socket
import threading
username = input("Your username : ")
host = "172.28.0.2"
port = 12344
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
def receive():
while True:
try:
message = client.recv(1024).decode("ascii")
if message == "NICK":
client.send(username.encode("ascii"))
else:
print(message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f"{username}: {input('')}"
client.send(message.encode("ascii"))
receive_thread = threading.Thread(target=receive)
receive_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
Basically I need the clients to be able connect to the server that is running on my computer from their computers without a local network.
The easist way is that your server can apply for a public IP in WLAN, not a private internal IP behind some router or NAT devices. It can also works if here is a relay server in public.
If you can't, then you need to do NAT traverse to pounch a hole, so that external clients can get in touch with the server which is behind router. For this, you can google and use TURN/STUN/ICE.

How to send messages to a remote computer using python socket module?

I'm trying to send a message from a computer to a another computer that is not connected to the other computer local network.
I did port forwarding (port 8080, TCP) and I didn't manage to get the remote computer to connect and to send the message.
when i try to connect it's just getting stuck on the connect method (client).
I also need to mention that I'm open to change anything in the router settings.
the client code (remote computer):
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("%My public IP address%", 8080))
msg = s.recv(1024)
msg = msg.decode("utf-8")
print(msg)
the server code:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("192.168.0.2", 8080))
s.listen(5)
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established.")
clientsocket.send(bytes("Hey there!!", "utf-8"))
clientsocket.close()
From my understanding, your aim is to connect to a server from a remote computer and send a message from the server to the client. As such, all it requires is the client to connect to the external-facing IP address of your server. Once that is done, router simply forwards the traffic according to the port forwarding rules.
Server:
import socket
def Main():
host = '10.0.0.140'
port = 42424
s = socket.socket()
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
while True:
data = c.recv(1024)
if not data:
break
data = str(data).upper()
c.send(data)
c.close()
if __name__ == '__main__':
Main()
Client:
import socket
def Main():
host = '10.0.0.140' #The host on your client needs to be the external-facing IP address of your router. Obtain it from here https://www.whatismyip.com/
port = 42424
s = socket.socket()
s.connect((host,port))
message = raw_input("->")
while message != 'q':
s.send(message)
data = s.recv(1024)
message = raw_input("->")
s.close()
if __name__ == '__main__':
Main()
Also do note that, When connecting to a server behind a NAT firewall/router, in addition to port forwarding, the client should be directed to the IP address of the router. As far as the client is concerned, the IP address of the router is the server. The router simply forwards the traffic according to the port forwarding rules.

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()

Categories

Resources