I have been working on a very simple group chat program. The program works well when tested on the same computer, but doesn't work between different computers on the INTERNET.
I have tried disabling Windows Fire Wall.
I cannot narrow down the code, Sorry.
The program uses a socket and Threading library.
Client Code:
import socket
import threading
SERVER_IP = "127.0.0.1" #This is changed to the servers PUBLIC IP when testing with another computer.
SERVER_PORT = 9279
global name
global sock
def connect():
global sock
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_addres = (SERVER_IP, SERVER_PORT)
try:
sock.connect(server_addres)
print("Connected.")
return 1
except:
print("Cant connect to server.")
return 0
def send_msg():
global sock
while True:
try:
msg = name + " >> " + input()
sock.sendall(msg.encode())
except Exception as e:
print(e)
def recieve_msg():
global sock
server_active = 1
while True and server_active:
try:
recieved_msg = sock.recv(1024).decode()
print("\n" + recieved_msg)
except Exception as e:
print(e)
server_active = 0
def main():
global name
name = input("Enter name: ")
connected = connect()
while True and connected:
send_thread = threading.Thread(target=send_msg)
send_thread.start()
recv_thread = threading.Thread(target=recieve_msg)
recv_thread.start()
while recv_thread.is_alive():
recv_thread.join(timeout=0.1)
sock.close()
Server code:
import socket
import _thread
host = "My private IP"
port = 9279
global thread_active
thread_active = 1
global client_list
client_list = []
global addr
def on_new_client(clientsocket, pt):
global thread_active
global client_list
while True and thread_active:
global addr
try:
msg = clientsocket.recv(1024).decode()
print(msg + " " + str(addr))
for client in client_list:
client.send(msg.encode())
except Exception as e:
print("Client " + str(addr[0]) + ':' + str(addr[1]) + " disconnected (" + str(e) + ")")
if clientsocket in client_list:
client_list.remove(clientsocket)
print(client_list)
thread_active = 0
s = socket.socket()
print('Server started!')
print('Waiting for clients...')
s.bind((host, port)) # Bind to the port
s.listen(10) # Now wait for client connection.
while True:
c, addr = s.accept()
print('Got connection from', addr)
client_list.append(c)
_thread.start_new_thread(on_new_client, (c, 0))
thread_active = 1
s.close()
clientsocket.close()
Related
How can I create a socket server that allows connections from other networks?
Currently, my server is running on my IPv4 address. This works fine. However, the server cannot be connected to from other networks. I know you can do port forwarding to get this to work, but how can I make the script automatically do port forwarding?
Here is my server code:
import socket, pickle
from _thread import *
from serverside import Player, get_chest_tiles
from maps import maps
server = '10.0.0.187'
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((server, port))
except socket.error as e:
print(e)
s.listen()
print(f'Server started with address: {server}, on port: {port}\nWaiting for connections...')
players = []
zombies = [False]
current_map = maps['town']
chest_tiles = get_chest_tiles(current_map[0])
def threaded_client(conn, player):
players.append(Player())
conn.sendall(pickle.dumps([players[player], player]))
while True:
reply = []
players_reply = []
try:
data = pickle.loads(conn.recv(999999))
if type(data) == list:
if data[0] == 'UPDATE_ZOMBIES':
global zombies
zombies = data[1]
elif data[0] == 'UPDATE_MAP':
global current_map
current_map = data[1]
else:
players[player] = data
if not data:
break
else:
for p in range(len(players)):
if p < player or p > player:
players_reply.append(players[p])
reply = [players_reply, current_map, zombies, chest_tiles]
conn.sendall(pickle.dumps(reply))
except:
break
print('Lost connection')
players.pop(player)
conn.close()
currentPlayer = 0
while True:
conn, addr = s.accept()
print('Connected to:', addr)
start_new_thread(threaded_client, (conn, currentPlayer))
currentPlayer += 1
I'm trying to make the clients be able to send messages to the server, right now clients can only send messages to each other, I have added the line where datafromclient but it only receives the first input by the client, after that only the clients exchange messages.
here is my code for server.py
import socket
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(),1234))
s.listen()
print("Waiting for connections")
clients = []
unames = []
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()
uname = unames[index]
broadcast(f"{uname} left the server!".encode("utf-8"))
unames.remove(uname)
break
def receive():
while True:
client, addr = s.accept()
print(f"Connected with {str(addr)}")
client.send('uname'.encode("utf-8"))
uname = client.recv(1024).decode("utf-8")
unames.append(uname)
clients.append(client)
broadcast(f"{uname} joined the server!".encode("utf-8"))
client.send("\nWelcome to the server!".encode("utf-8"))
fOpen = open("rules.txt", "r")
client.send(fOpen.read().encode("utf-8"))
datafromclient = client.recv(1024)
print(datafromclient.decode("utf-8"))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
receive()
s.close()
And this is client.py
import socket
import threading
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect((socket.gethostname(),1234))
uname = input("Username: ")
def receive():
while True:
try:
message = c.recv(1024).decode("utf-8")
if message == "uname":
c.send(uname.encode("utf-8"))
else:
print(message)
except:
print("An error occurred!")
c.close()
break
def write():
while True:
message = f'{uname}: {input("")}'
c.sendall(message.encode("utf-8"))
recv_thread = threading.Thread(target=receive)
recv_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
This should give you an idea:
server.py:
import socket
import threading
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((socket.gethostbyname(socket.gethostname()), 1234))
clients = []
def handle_client(conn, addr):
clients.append(conn)
while True:
msg_length = conn.recv(64).decode("utf-8")
if msg_length:
msg = conn.recv(int(msg_length)).decode("utf-8")
print(msg)
if msg == "!DISCONNECT":
break
for client in clients:
client.send(msg.encode("utf-8"))
clients.remove(conn)
conn.send('Bye'.encode("utf-8"))
conn.close()
server.listen()
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
client.py:
import socket
import threading
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((socket.gethostbyname(socket.gethostname()), 1234))
def send():
msg = input(">>> ")
client.send(str(len(msg)).encode("utf-8").ljust(64))
client.send(msg.encode("utf-8"))
thread = threading.Thread(target=send)
thread.start()
while True:
if client.recv(2048).decode("utf-8") == "Bye":
break
thread = threading.Thread(target=send)
thread.start()
I was following a tutorial and got stuck here. When I ran the same code for the first time, It went well. But from the second time, it shows error in the same code. I restarted my computer and then it ran once and from the second time, it again shows error.
#THE CODE:
import socket
from _thread import *
import sys
server = "192.168.0.102"
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((server, port))
except socket.error as e:
str(e)
s.listen(2)
print("Waiting for a connection , Server Started")
def read_pos(str):
str = str.split(",")
return int(str[0]), int(str[1])
def make_pos(tup):
return str(tup[0]) + "," + str(tup[1])
pos = [(0, 0), (100, 100)]
def threaded_client(conn, player):
conn.send(str.encode(make_pos(pos[player])))
reply = ""
while True:
try:
data = read_pos(conn.recv(2048).decode())
pos[player] = data
if not data:
print("Disconnected")
break
else:
if player == 1:
reply = pos[0]
else:
reply = pos[1]
print("Received : ", data)
print("Sending: ", reply)
conn.sendall(str.encode(make_pos(reply)))
except:
break
print("Lost Connection")
conn.close()
currentPlayer = 0
while True:
conn, addr = s.accept()
print("Connected to : ", addr)
start_new_thread(threaded_client, (conn, currentPlayer))
currentPlayer += 1
Try using a different IP address. The code worked correctly when I used 127.0.0.1 which is the local machine.
server = "127.0.0.1"
port = 5555
Why is it that the following server code cannot seem to accept new connections with clients even after the first connection is closed?
def bindPort(port):
global return_response
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
serverSocket.bind(('', port))
except:
print("Cannot bind to port. Error: " + str(sys.exc_info))
serverSocket.listen(2)
print("The server is ready to receive")
count = 0
while True:
connectionSocket, addr = serverSocket.accept()
count += 1
print("Accepted {} connections so far.".format(count))
print('Connection established from {}'.format(addr))
while True:
sentence = connectionSocket.recv(1024)
if not sentence:
print("Empty")
break
print(sentence)
#parseIncomingRequest(sentence.decode())
print(return_response)
connectionSocket.send(return_response.encode())
return_response = ''
print("Closing loop")
connectionSocket.close()
I apologize for not reading the question properly
1)declare the return response variable before you use it
2)break out of the second while loop if you want accept an other connection .In the question you said that no connections were being accepted after the socket was closed but for the socket to close you have to break out out of the second while loop.or in my opinion you should remove the second loop .
3)if you want to keep listening on the socket and still be able to receive other connections use the threading module
def bindPort(port):
global return_response
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
serverSocket.bind(('', port))
except:
print("Cannot bind to port. Error: " + str(sys.exc_info))
serverSocket.listen(2)
print("The server is ready to receive")
count = 0
while True:
connectionSocket, addr = serverSocket.accept()
count += 1
print("Accepted {} connections so far.".format(count))
print('Connection established from {}'.format(addr))
sentence = connectionSocket.recv(1024)
if not sentence:
print("Empty")
break
print(sentence)
#parseIncomingRequest(sentence.decode())
return_response = ''
print(return_response)
connectionSocket.send(return_response.encode())
connectionSocket.shutdown(socket.SHUT_RDWR)
connectionSocket.close()
4)or if you want to keep the loop for further modfication
import socket
def bindPort(port):
global return_response
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
serverSocket.bind(('', port))
except:
print("Cannot bind to port. Error: " + str(sys.exc_info))
serverSocket.listen(2)
print("The server is ready to receive")
count = 0
while True:
connectionSocket, addr = serverSocket.accept()
count += 1
print("Accepted {} connections so far.".format(count))
print('Connection established from {}'.format(addr))
while True:
sentence = connectionSocket.recv(1024)
if not sentence:
print("Empty")
break
print(sentence)
#parseIncomingRequest(sentence.decode())
return_response = 'a'
print(return_response)
connectionSocket.send(return_response.encode())
break
print("Closing loop")
connectionSocket.shutdown(socket.SHUT_RDWR)
connectionSocket.close()
Output at console server
I am trying to write bi-directional UDP communication using multithread but it crashes after sending two messages. Also i am new to threading so please post your solution on this.
Thanks
Server side:
import threading
from threading import Thread
import socket
from socket import *
import time
import pymongo
from datetime import datetime
from time import ctime
#broadcast works for this program
import netifaces
import os
import re
import struct
class cont():
def get_msg(self):
UDP = "192.168.1.27"
port = 4343
address = UDP, port
self.sock = socket(AF_INET, SOCK_DGRAM)
self.sock.bind(address)
while True:
r = self.sock.recvfrom(1000)
print("controller1: %s" % (r[0]))
reply = input('Main controller : ')
client_address = r[1]
self.sock.sendto(bytearray(reply, "utf-8"), client_address)
t2 = threading.Thread(target=self.get_msg, args=(reply,))
t2.start()
if __name__=='__main__':
c=cont()
#c.broad(msg="")
c.get_msg()
Client side:
UDP=""
port=4343
address=UDP,port
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while(True):
msg=input("Controller1")
client.sendto(bytearray(msg,"utf-8"),address)
reply=client.recvfrom(1000)
recved=str(reply)
print("Main Controller:% s" % recved))
Output required :
Server Console:
Client:b'hello'
Server:b'hi
Client Console:
Client: b'hello'
Server : (b'hi',('ip',port)
Here is a TCP class I made for communicating with my robots, can be easily modified for UDP. Might seem like a lot of code, but it's what it takes for "reliable" "two way" communication, without blocking your main program. I use processes instead of threads because threads in python aren't "real" threads due to the global interpreter lock.
import socket
from multiprocessing import Process, Queue, Event, Value
import traceback
class SocketComm(object):
def __init__(self,port):
self.address = ""
self.otherAddress = object
self.port = port
self.finished = Value("b", True)
self.inbox = Queue()
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.getMessagesProcess = Process(target=self.getMessages)
self.getMessagesProcess._stop_event = Event()
self.getMessagesProcess.daemon = True
self.connected = False
self.timeout = 3
return
def setupLine(self, addr):
self.address = addr
if self.address is "": #i.e. server on raspberry pi
try:
self.connection.settimeout(self.timeout)
self.connection.bind((self.address, self.port))
print("binding with port: " + str(self.port))
self.connection.listen(1)
self.connection, self.otherAddress = self.connection.accept()
print("connected to client at: " + self.otherAddress[0])
except socket.error as e:
print(str(e))
return False
else:
try:
#print("connecting to port: " + str(self.port))
self.connection.connect((self.address, self.port)) # i.e. client
print("connected to server")
except socket.error as e:
#print(str(e))
return False
self.getMessagesProcess.start()
self.connected = True
self.finished.value = False
print("inbox at: " + str(id(self.inbox)))
return True
def sendMessage(self, msg):
try:
self.connection.send(str.encode(msg))
#print("sent: " + str(msg))
except Exception as e:
pass
#print(str(e))
#traceback.print_exc()
#print("exception caught.")
return
def getMessages(self):
#print("getting messages now")
self.connection.settimeout(1)
while(not self.finished.value):
#print("checking inbox")
#print("inbox length: " + str(len(self.inbox)))
try:
received = self.connection.recv(1024)
decoded = received.decode('utf-8')
if len(decoded) > 0:
if(decoded == "end"):
self.finished.value = True
else:
self.inbox.put(decoded)
print("received: " + str(decoded))
except socket.error as e:
if(type(e).__name__ == "timeout"):
pass
else:
print("endpoint closed.")
self.finished.value = True
return
def closeConnection(self):
if(self.connected):
self.finished.value = True
self.getMessagesProcess._stop_event.set()
self.sendMessage("end")
try:
self.getMessagesProcess.join()
except:
print("process already finished.")
self.connection.close()
return
##
##if(__name__ == "__main__"):
## robotClient = SocketComm(5555)
## robotClient.setupLine("127.0.0.1")
## while(robotClient.finished.value == False):
## val = input("enter something: ")
## if(len(val) > 0):
## robotClient.sendMessage(val)
##
##
##if(__name__ == "__main__"):
## try:
## robotServer = SocketComm(5555)
## print("waiting for client to connect...")
## robotServer.setupLine("")
## print("connected!")
## while(robotServer.finished.value == False):
## val = input("enter something: ")
## if(len(val) > 0):
## robotServer.sendMessage(val)
## except:
## pass
## finally:
## robotServer.closeConnection()
## sys.exit(0)