Python How to build a *real* ip address multi-client server - python

let's say I have a multi-client server socket and a client socket in python.
Server: (You don't have to read all of the server's code, just know it's a multi-client server.
import socket, select
CONNECTION_LIST = [] # list of socket clients
RECV_BUFFER = 4096 # Advisable to keep it as an exponent of 2
PORT = 5000
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# this has no effect, why ?
RealServerIP = ? # I want to have a real server ip which would let me connect to the server from any computer around the globe...
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((RealServerIP, PORT))
server_socket.listen(10)
# Add server socket to the list of readable connections
CONNECTION_LIST.append(server_socket)
print "Chat server started on port " + str(PORT)
while 1:
# Get the list sockets which are ready to be read through select
read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])
for sock in read_sockets:
#New connection
if sock == server_socket:
# Handle the case in which there is a new connection recieved through server_socket
sockfd, addr = server_socket.accept()
CONNECTION_LIST.append(sockfd)
print "Client (%s, %s) connected" % addr
#Some incoming message from a client
else:
# Data recieved from client, process it
try:
#In Windows, sometimes when a TCP program closes abruptly,
# a "Connection reset by peer" exception will be thrown
data = sock.recv(RECV_BUFFER)
# echo back the client message
if data:
sock.send(data)
# client disconnected, so remove from socket list
except:
broadcast_data(sock, "Client (%s, %s) is offline" % addr)
print "Client (%s, %s) is offline" % addr
sock.close()
CONNECTION_LIST.remove(sock)
continue
server_socket.close()
(example from http://www.binarytides.com/code-chat-application-server-client-sockets-python/).
And 3 clients which are the most simple clients you can imagine to yourself:
import socket # imports module named 'socket'
RealServerIP = ? # I need your help here.... read the continuation
my_socket = socket.socket() # creates new socket named 'my_socket'
my_socket.connect((RealServerIP, 5000)) # connects to the server
my_socket.send(str) # sends string to the server
data = my_socket.recv(1024)
print data # prints data
my_socket.close()
I wanted to check whether my server can comunicate with those 3 clients at the same time. So I want to make my server as a public server like a web-server of Facebook, etc.
So any computer around the world could connect to it.
So, I tried to figure out how would I store my python server socket online with a specific IP and PORT which has nothing to do with my localhost, I want it to be real! Like any chat/web server you know..

If you mean the IP which the user connect with it to the internet, I don't think there is a way to get it by socket module, But i got a way to do the same thing using requests module if this may help.
import requests
def get_ip():
url = 'https://www.cmyip.com'
user_ip = requests.get(url).content.decode("utf-8").split("My IP Address is ")[1].split(" <a class=")[0]
return user_ip
I hope this help.
Note: This was tested on python 3.4.3 and it is working fine. I don't know about 2.X versions.

Related

Python socket throwing the following error ConnectionResetError: [Errno 54] Connection reset by peer

I have been trying to create a messaging service in python using sockets. I have written the code to host two connections and allow one to send messages to the other using username and host_addr.
But every time I try to connect the second client and send a message from the first getting the following error.
ConnectionResetError: [Errno 54] Connection reset by peer
Server.py
import socket
import _thread as thread
HOST = "127.0.0.1" # Standard loopback interface address (localhost)
PORT = 1237 # Port to listen on (non-privileged ports are > 1023)
user_mapping = {}
def on_new_client(conn, addr):
data = conn.recv(1024)
data = data.decode()
print(data)
print(user_mapping)
if data[:8] == "username":
user_mapping[data[9:]] = (addr, data[9:])
elif data[0] == "#":
for i in user_mapping.values():
if i[0] == addr:
from_user = i[1]
else:
str = "user not found"
conn.sendto(str.encode(), addr)
str = "%s:%s" % (from_user, data[data.find(":") + 1:])
conn.sendto(str.encode(), user_mapping[data[1:data.find(":")](0)])
else:
pass
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(10)
while True:
conn, addr = s.accept()
thread.start_new_thread(on_new_client,(conn,addr))
s.close()
Client.py
import socket
HOST = "127.0.0.1" # The server's hostname or IP address
PORT = 1237 # The port used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
username = input("Enter user name")
str = "username: %s" % username
s.send(str.encode())
while True:
message = input(username+">")
s.send(message.encode())
data = s.recv(1024)
print(data)
Was hoping some would could answer why this is happening and guide me to any good links where there is Information on creating a messaging service in python.
Client is sending 2 messages and then receiving one.
But server just listen once and then send one or two packages.
Chronologically:
Client sends a package, and server reads it.
Then both client and server try to send a package. Both packages that won't meet a listening peer.
Then client try to receive a package, but server won't send (he already sent it before) or it may send but its too late because communication is already broken.
Concepts you may implement always:
If one talk, another one may listen.
If a package is mean to be sent, it shall be sent anyway. Dont let a 'if' statment that send package when at 'else' that does not (or viceversa).
==== EDIT ====
About solution:
You need to work with paralel loops.
Take a look at this code https://www.neuralnine.com/tcp-chat-in-python/
He uses two threads on client, one for keep listening for new server updates (messages for other people) and another one to wait input from user.

Python Socket, how do i choose between s.send and conn.send?

def send_Button():
try:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
except NameError:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
This program uses the tkinter module with socket in python2.7. My program allows for you to either connect to a server to chat with or host a server for others to connect to you, but whenever I try and test it out then the lines with the '###' on always bring up an error and it doesn't work, the error which comes up is: "NameError: global name 'conn' is not defined" OR "error: [Errno 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied".
Any help please?
I think that you are trying to get the program to act as a Client or as a Server just changing s.send() to conn.send() saddly it isn't that simple.
Socket Initializzation
The socket have to be initialized before sending or receiving data.
For a client usually it's something like this.
send_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
send_socket.connect((serverIp, serverPort)) # Connect to the server
send_socket.send(data) # Send the data to the server
And like this for a Server:
listen_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
listen_socket.bind(("0.0.0.0", port)) # Set the socket to accept client from every interface on the port port
listen_socket.listen(1) # Put the server on listen on the port setted before
accept_socket, addr = self.listen_socket.accept() # when a client connect return the socket to talk with it
data = self.accept_socket.recv(buffer_size) # Receive data form the client of max size buffer_size
Docs examples
From your question I guess that with s.send() and conn.send() you are talking about
this example from the python 2.7 socket docs
Here are four minimal example programs using the TCP/IP protocol: a server that echoes all data that it receives back (servicing only one client), and a client using it. Note that a server must perform the sequence socket(), bind(), listen(), accept() (possibly repeating the accept() to service more than one client), while a client only needs the sequence socket(), connect(). Also note that the server does not sendall()/recv() on the socket it is listening on but on the new socket returned by accept().
Client
Echo client program
import socket
HOST = 'daring.cwi.nl' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
the client is pretty stright forward, it create the socket s and then after using s.connect() it just send data through it.
Server
The server one is where there there are both s and conn
Echo server program
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
conn.close()
in this one first of all we create a socket s on which the server will listen and then using s.accept() it will wait till a client connect to the server and then return the conn which is the socket of the connected client.
So to receive or send data to the client you have to use conn.
Notes
As said in the documentation in these two example the server accept only one client. So if you want to deal with multiple clients you have to repeat the accept step and possibly generate a new Thread for each client so that other clients don't have to wait for each others.

How would I use these two Python chat room codes (server and client) to talk between different computers?

I've been looking for a project to do over the winter holidays and have found some people's codes for Python Chat rooms.
I have both a server script, and a client script up and working. But i can only make it work if they are on the same computer. I've tried having the client on a different computer, but i can't seem to make it work (it says it can't connect).
Here is the server code:
# Tcp Chat server
import socket, select
#Function to broadcast chat messages to all connected clients
def broadcast_data (sock, message):
#Do not send the message to master socket and the client who has send us the message
for socket in CONNECTION_LIST:
if socket != server_socket and socket != sock :
try :
socket.send(message)
except :
# broken socket connection may be, chat client pressed ctrl+c for example
socket.close()
CONNECTION_LIST.remove(socket)
if __name__ == "__main__":
# List to keep track of socket descriptors
CONNECTION_LIST = []
RECV_BUFFER = 4096 #exponent of 2
PORT = 2015
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# this has no effect, why ?
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("0.0.0.0", PORT))
server_socket.listen(10)
# Add server socket to the list of readable connections
CONNECTION_LIST.append(server_socket)
print ("Chat server started on port " + str(PORT))
while 1:
# Get the list sockets which are ready to be read through select
read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])
for sock in read_sockets:
#New connection
if sock == server_socket:
# Handle the case in which there is a new connection recieved through server_socket
sockfd, addr = server_socket.accept()
CONNECTION_LIST.append(sockfd)
print("Client (%s, %s) connected" % addr)
broadcast_data(sockfd, "[%s:%s] entered room\n" % addr)
#Some incoming message from a client
else:
# Data recieved from client, process it
try:
#In Windows, sometimes when a TCP program closes abruptly,
# a "Connection reset by peer" exception will be thrown
data = sock.recv(RECV_BUFFER)
if data:
#broadcast_data(sock, "\r" + '<' + str(sock.getpeername()) + '> ' + data)
broadcast_data(sock, "\r" + data)
except:
broadcast_data(sock, "Client (%s, %s) is offline" % addr)
print ("Client (%s, %s) is offline" % addr)
sock.close()
CONNECTION_LIST.remove(sock)
continue
server_socket.close()
Here is the code for the client:
#Chat Client
import socket, select, string, sys
NName = ""
def prompt() :
sys.stdout.write('<{0}> '.format(NName))
sys.stdout.flush()
#main function
if __name__ == "__main__":
if(len(sys.argv) < 3) :
print('Usage : python TCP_Client.py hostname port')
sys.exit()
host = sys.argv[1]
port = int(sys.argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
# connect to remote host
try :
s.connect((host, port))
except :
print('Unable to connect')
sys.exit()
print('Connected to remote host.')
print('Enter your Nickname:')
NName = raw_input(" ")
prompt()
while 1:
socket_list = [sys.stdin, s]
# Get the list sockets which are readable
read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])
for sock in read_sockets:
#incoming message from remote server
if sock == s:
data = sock.recv(4096)
if not data :
print ('\nDisconnected from chat server')
sys.exit()
else :
#print data
sys.stdout.write(data)
prompt()
#user entered a message
else :
msg = sys.stdin.readline()
s.send("<{0}> {1}".format(NName,msg))
prompt()
I'm not looking for any improvements over the program, i just want to know how i'm supposed to make the client connect to the server from a different computer.
Thanks,
Gibbon :)
EDIT
Okay, i realised i probably didn't have enough information here:
What I am doing at the moment:
In OSX terminal:
python /path/to/file/TCP_Server
And in another OSC terminal (On a different computer) (Replacing 'xxx.xxx...' with the computer running the server's ip addres:
python /path/to/file/TCP_Client xxx.xxx.xxx.xxx 2015
These Server/client codes are benefit and useful to learn and windows 10 u must modify smart screen, windows defender turn off.
I prefer that u can entered the 10.0.0.134/135/138 ip address with use wireless usb card and use wingIDE instead of IDLE environment of programming. Python is better than perl and is more flexibility than anothers programming like that php 7.0 I am fans of that. Go on python on azure microsoft and use for e-commerce destination.
Programming makes perfect with low level of language programming.

Setting up non-blocking socket for Jython for use in Chat server

I'm trying to create a Jython(actually monkeyrunner) program which receives messages from other python(CPython because it uses OpenCV)
First, I tried to implement a chatting program example(server-side) and I ran into a problem.
While the example uses Blocking-socket for select, the Jython select cannot support it.
Therefore, I put the code 'server_socket.setblocking(0)' when setting the socket, but nothing changed.
Also, I tried 'from select import cpython_compoatible_select as select', but it causes Attribute error, 'function' object has no attribute 'select'.
Below is my code
# coding: iso-8859-1
import socket,select
#Function to broadcast chat messages to all connected clients
def broadcast_data (sock, message):
#Do not send the message to master socket and the client who has send us the message
for socket in CONNECTION_LIST:
if socket != server_socket and socket != sock :
try :
socket.send(message)
except :
# broken socket connection may be, chat client pressed ctrl+c for example
socket.close()
CONNECTION_LIST.remove(socket)
if __name__ == "__main__":
# List to keep track of socket descriptors
CONNECTION_LIST = []
RECV_BUFFER = 4096 # Advisable to keep it as an exponent of 2
PORT = 5000
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# this has no effect, why ?
#JYTHON never supports blocking-mode socket so make it unblock
server_socket.setblocking(0)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("0.0.0.0", PORT))
server_socket.listen(10)
# Add server socket to the list of readable connections
CONNECTION_LIST.append(server_socket)
print "Chat server started on port " + str(PORT)
while 1:
# Get the list sockets which are ready to be read through select
#JYTHON never supports blocking-mode socket so make it unblock
server_socket.setblocking(0)
read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])
for sock in read_sockets:
#New connection
if sock == server_socket:
# Handle the case in which there is a new connection recieved through server_socket
#JYTHON never supports blocking-mode socket so make it unblock
server_socket.setblocking(0)
sockfd, addr = server_socket.accept()
CONNECTION_LIST.append(sockfd)
#print "Client (%s, %s) connected" % addr
broadcast_data(sockfd, "[%s:%s] entered room\n" % addr)
#Some incoming message from a client
else:
# Data recieved from client, process it
try:
#In Windows, sometimes when a TCP program closes abruptly,
# a "Connection reset by peer" exception will be thrown
data = sock.recv(RECV_BUFFER)
if data:
print data
broadcast_data(sock, "\r" + '<' + str(sock.getpeername()) + '> ' + data)
except:
broadcast_data(sock, "Client (%s, %s) is offline" % addr)
print "Client (%s, %s) is offline" % addr
sock.close()
CONNECTION_LIST.remove(sock)
continue
server_socket.close()
#see http://www.binarytides.com/code-chat-application-server-client-sockets-python/
and my error message
C:\NVPACK\android-sdk-windows\tools\lib>monkeyrunnerUTF chatserver.py
Chat server started on port 5000
130815 17:06:17.418:S [MainThread] [com.android.monkeyrunner.MonkeyRunnerOptions
] Script terminated due to an exception
130815 17:06:17.418:S [MainThread] [com.android.monkeyrunner.MonkeyRunnerOptions
]Traceback (most recent call last):
File "C:\NVPACK\android-sdk-windows\tools\chatserver.py", line 41, in <module>
read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],
[])
File "C:\NVPACK\android-sdk-windows\tools\lib\jython-standalone-2.5.3.jar\Lib\
select.py", line 225, in native_select
File "C:\NVPACK\android-sdk-windows\tools\lib\jython-standalone-2.5.3.jar\Lib\
select.py", line 106, in register
select.error: (20000, 'socket must be in non-blocking mode')
Thank you in advance :)
AndroidViewClient's tests implement a MockViewServer using monkeyrunner, setting the socket as non-blocking and using
from select import cpython_compatible_select as select
for select.
See the source code at https://github.com/dtmilano/AndroidViewClient/blob/master/AndroidViewClient/tests/com/dtmilano/android/mocks.py#L758
This works on Linux and OSX (your mileage may vary with Windows)

Server send data in python

I'm writing a simple client server app in python, where the client is listening every type of data entering in the specific port, and I want to when receiving a data flow, send back to the connected client (which have a dinamic ip) a string, in this case "001". But when I try to send the message, it fails!
#!/usr/bin/env python
import socket
TCP_IP = '192.168.1.115'
TCP_PORT = 55001
BUFFER_SIZE = 1024
MESSAGE = '01'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print ('Connection address:', addr)
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print ('received data:', data)
conn.send(data) # echo
print ('Sending data to client...')
addr change every connection .. i cannot manage this!
s.connect((addr, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
(Connected stream) sockets are bidirectional, so there's no need to call connect to get a connection to the client—you already have one.
But you want to know why your code fails. And there are at least three problems with it.
First, after you call listen or connect on a socket, you can't call connect again; you will get an exception (EISCONN on POSIX, something equivalent on Windows). You will have to create a new socket.
Second, is client actually binded and listening for a connection on the same port as the server? If not, your connect can't work. If so, the bind will fail if the client and server are on the same machine.
Third, the addr you get back from accept is a (host, port) pair, not just a host. So, as written, you're trying to connect((('192.168.1.115', 12345), 55001)), which obviously isn't going to work.
You are trying to reply to the client using the server listening socket (s). This is only possible in UDP Servers. Since this is a TCP Server you have to use the conn which is crated using s.accept() to communication with remote client.

Categories