I'm trying to make a simple Peer to Peer Network in Python 2.7. The problem is, I can't seem to be able to create a connection between two machines in which they both act as a server and a client. I can get it to work when one is a server and the other is a client but not when they are both, both. Do I need to create 2 sockets? Also I'm using TCP to connect.
UPDATE:
import socket, sys # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
if sys.argv[1] == "connect":
host = sys.argv[2]
s.connect((host, port))
s.close
else:
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close()
The codes not very good because for someone to connect as a client they have to use the argument "connect" followed by the hostname or IP of the second machine. I can't get the two to connect and serve to each other simultaneously.
Yes, two sockets are necessary. The listening socket should open on a constant port, and the client port should be opened on a different (potentially dynamic) port, usually higher in the port range. As an example:
Server sockets on port 1500, client sockets on port 1501.
Peer1: 192.168.1.101
Peer2: 192.168.1.102
When peer1 connects to peer2 it looks like this: 192.168.1.101:1501 -> 192.168.1.102:1500.
When peer2 connects to peer1 it looks like this: 192.168.1.102:1501 -> 192.168.1.101:1500.
Listening TCP sockets are also generally run on a separate thread since they are blocking.
Yes, you'll need to use two sockets, one for accepting connections (server) and one for initiating connections (client). However, you can bind both sockets to the same local port, using that port number as both the source and destination port and thereby ensuring that you'll end up with only a single connection between each pair of peers. If both peers try to connect simultaneously (e.g. because they discovered each other at the same time), one of the client connection attempts will fail (where the peer's server socket accepted the connection), you'll have to handle (ignore) that.
To bind two sockets on the same port, you'll need to set the SO_REUSEPORT/SO_REUSEADDR flags on both.
Here is an example program demonstrating this technique (using the excellent trio on Python 3):
from errno import EADDRNOTAVAIL
from functools import partial
from itertools import count
import trio
import socket
async def peer(SRC, DEST):
counter = count(start=1)
async def sender(stream, n):
print(f"sender{n}#{SRC}: started!")
while True:
data = bytes(f"Hello from {n}#{SRC}", "utf8")
print(f"sender{n}#{SRC}: sending {data!r}")
await stream.send_all(data)
await trio.sleep(1)
async def receiver(stream, n):
print(f"receiver{n}#{SRC}: started!")
async for data in stream:
print(f"receiver{n}#{SRC}: got data {data!r}")
print(f"receiver{n}#{SRC}: connection closed")
async with trio.open_nursery() as nursery:
async def run(connection: trio.SocketStream):
count = next(counter)
print(f"peer#{SRC} got connection{count} from {method}() with {connection.socket.getpeername()}")
async with connection:
async with trio.open_nursery() as nursery:
print(f"peer#{SRC}: spawning sender...")
nursery.start_soon(sender, connection, count)
print(f"peer#{SRC}: spawning receiver...")
nursery.start_soon(receiver, connection, count)
print(f"peer: listening at {SRC}")
servers = await trio.open_tcp_listeners(SRC[1], host=SRC[0])
servers[0].socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
servers[0].socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
await nursery.start(trio.serve_listeners, partial(run, "listen"), servers)
print(f"peer: connecting from {SRC} to {DEST}")
client = trio.socket.socket()
client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
await client.bind(address=SRC)
try:
await client.connect(address=DEST)
except OSError as err:
if err.errno != EADDRNOTAVAIL:
raise
# the other client was faster than us
print(f"peer#{SRC}: {err.strerror}")
else:
await run('connect', trio.SocketStream(client))
async def main():
async with trio.open_nursery() as nursery:
a = ("127.0.0.1", 12345)
b = ("127.0.0.1", 54321)
nursery.start_soon(peer, a, b)
nursery.start_soon(peer, b, a)
trio.run(main)
In this small demonstration, the two peers run within the same program on different ports on the same host, but it works just the same with two programs using the same ports but different hosts. Notice that if you comment out the client.bind(address=SRC) bit, they will use ephemeral source ports, and create two separate connections not just a single one.
Related
So far I managed to get the server to communicate with multiple clients but I need to pass a value from one client to another.
Server code
import socket
from _thread import *
ServerSideSocket = socket.socket()
host = ''
port = 2004
ThreadCount = 0
try:
ServerSideSocket.bind((host, port))
except socket.error as e:
print(str(e))
print('Socket is listening..')
ServerSideSocket.listen(5)
def multi_threaded_client(connection):
connection.send(str.encode('Server is working:'))
while True:
data = connection.recv(2048)
response = data.decode('utf-8')
if not data:
break
connection.sendall(str.encode(response))
connection.close()
while True:
Client, address = ServerSideSocket.accept()
print('Connected to: ' + address[0] + ':' + str(address[1]))
start_new_thread(multi_threaded_client, (Client,))
ThreadCount += 1
print('Thread Number: ' + str(ThreadCount))
ServerSideSocket.close()
Client code
import socket
ClientMultiSocket = socket.socket()
host = '127.0.0.1'
port = 2004
print('Waiting for connection response')
try:
ClientMultiSocket.connect((host, port))
except socket.error as e:
print(str(e))
res = ClientMultiSocket.recv(1024)
while True:
Input = input('Hey there: ')
ClientMultiSocket.send(str.encode(Input))
res = ClientMultiSocket.recv(1024)
print(res.decode('utf-8'))
ClientMultiSocket.close()
I need the value from client1 to be passed to client2 and so forth, is there any way I can do that in python?
A TCP connection can only established to a socket which is a) bound to the specific address one is trying to connect to and b) is listening on this address for new connections which it then will c) accept to create a new socket which will then be used to communicate on this connection. Any communication outside such established connection is not possible in TCP.
The combination of a, b and c basically describes what a TCP server does. This also means that it is not possible to communicate between two TCP clients only which only called connect to each other. In order for a connect to succeed there must be something bound to the socket, listening to it and accepting connections on it (i.e. a, b and c - a TCP server).
A common way to implement the use cases of passing messages between different client (like in a chat server) is to send the message and intended client id to the server and let the server forward it to the intended client.
In a TCP connection, always, one is the server and the other are the client.
A simple use case:
client1 need to send a msg to client2, the pipeline could be:
client1 send a msg in JSON format to server "{'msg': 'abc',
'receiver':'client2'}"
server will store this info in a dict (or another structure you want)
client2 will ask for the server if there is any message to it
the server send the message stored to client2
It's more or less in this way that all the communications apps works.
hi i make model server client which works fine and i also create separate GUI which need to two input server IP and port it only check whether server is up or not. But when i run server and then run my GUI and enter server IP and port it display connected on GUI but on server side it throw this error. The Server Client working fine but integration of GUI with server throw below error on server side.
conn.send('Hi'.encode()) # send only takes string BrokenPipeError: [Errno 32] Broken pip
This is server Code:
from socket import *
# Importing all from thread
import threading
# Defining server address and port
host = 'localhost'
port = 52000
data = " "
# Creating socket object
sock = socket()
# Binding socket to a address. bind() takes tuple of host and port.
sock.bind((host, port))
# Listening at the address
sock.listen(5) # 5 denotes the number of clients can queue
def clientthread(conn):
# infinite loop so that function do not terminate and thread do not end.
while True:
# Sending message to connected client
conn.send('Hi'.encode('utf-8')) # send only takes string
data =conn.recv(1024)
print (data.decode())
while True:
# Accepting incoming connections
conn, addr = sock.accept()
# Creating new thread. Calling clientthread function for this function and passing conn as argument.
thread = threading.Thread(target=clientthread, args=(conn,))
thread.start()
conn.close()
sock.close()
This is part of Gui Code which cause problem:
def isOpen(self, ip, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, int(port)))
data=s.recv(1024)
if data== b'Hi':
print("connected")
return True
except:
print("not connected")
return False
def check_password(self):
self.isOpen('localhost', 52000)
Your problem is simple.
Your client connects to the server
The server is creating a new thread with an infinite loop
The server sends a simple message
The client receives the message
The client closes the connection by default (!!!), since you returned from its method (no more references)
The server tries to receive a message, then proceeds (Error lies here)
Since the connection has been closed by the client, the server cannot send nor receive the next message inside the loop, since it is infinite. That is the cause of the error! Also there is no error handling in case of closing the connection, nor a protocol for closing on each side.
If you need a function that checks whether the server is online or not, you should create a function, (but I'm sure a simple connect is enough), that works like a ping. Example:
Client function:
def isOpen(self, ip, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((str(ip), int(port)))
s.send("ping".encode('utf-8'))
return s.recv(1024).decode('utf-8') == "pong" # return whether the response match or not
except:
return False # cant connect
Server function:
def clientthread(conn):
while True:
msg = conn.recv(1024).decode('utf-8') #receiving a message
if msg == "ping":
conn.send("pong".encode('utf-8')) # sending the response
conn.close() # closing the connection on both sides
break # since we only need to check whether the server is online, we break
From your previous questions I can tell you have some problems understanding how TCP socket communication works. Please take a moment and read a few articles about how to communicate through sockets. If you don't need live communications (continous data stream, like a video, game server, etc), only login forms for example, please stick with well-known protocols, like HTTP. Creating your own reliable protocol might be a little complicated if you just got into socket programming.
You could use flask for an HTTP back-end.
I'm trying to make a Python server where multiple clients can connect but I've run into a problem I tried everything that I found on the internet.
I'm running a laptop whit windows 7 and an I3 processor.
This is the file called tcp:
import socket
def make_server (ip,port):
try:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ip, port))
server.listen(1)
return server
except Exception as ex:
print(ex)
return None
def accept(server):
conn, addr = server.accept()
return conn
def make_client():
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
return client
def client_connect(client,ip,port):
client.connect((ip,port))
def sendall(conn,mess):
conn.send(str(mess).encode("utf-8"))
def rec(conn,rate):
mess = conn.recv(rate).decode("utf-8")
return mess
def close(client):
client.close()
This is the server:
from multiprocessing import Process
from random import randint
import tcp
import sys
def start(sip, sport):
print("Making sob server...")
print("id= {}".format(sport))
sserver = tcp.make_server(sip, sport)
print("Sub Server Started!")
sconn = tcp.accept(sserver)
tcp.sendall(sconn, "connected!!")
while True:
try:
tcp.sendall(sconn, randint(0, 100))
except Exception as ex:
print("")
print("From server {} error:".format(port))
print(ex)
print("")
break
ip = "192.168.0.102"
port = 8000
subport = 9000
server = tcp.make_server(ip, port)
if server is None:
sys.exit(0)
print("Started!")
while True:
print("Wating for new connection!")
con = tcp.accept(server)
print("Connected!")
subport = subport + 1
tcp.sendall(con, subport)
print("New Port Sent!")
print("New Port = {}".format(subport))
subs = Process(target=start, args=(ip, subport))
subs.start()
subs.join()
This is the client:
import tcp
import time
nport = 0
ip = "192.168.0.102"
port = 8000
client = tcp.make_client()
tcp.client_connect(client,ip,port)
nport = tcp.rec(client,1024)
print(nport)
tcp.close(client)
nport = int(nport)
time.sleep(1)
print(nport)
client = tcp.make_client()
tcp.client_connect(client,ip,nport)
while True:
mess = tcp.rec(client, 1024)
if(mess):
print(mess)
The error is:
[WinError 10048]Only one usage of each socket address (protocol/network address/port) is normally permitted Python
Feel free to change anything you want.
If you need any info in plus just ask.
You are creating a socket in the client with tcp.make_client. You are then using that socket to connect to the server via tcp.client_connect. Presumably you successfully receive the new port number back from the server. But then you are trying to re-use the same socket to connect to those ports.
This is the proximate cause of your error: A socket can only be used for a single TCP connection. If you want to create a new connection, you must first create a new socket.
That being said, if you are simply trying to create a server that will accept multiple connections, you're making it way too complicated. The server can receive any number of connections on its single listening port, as long as a different address/port combination is used by each client.
One way to structure this in a server is something like this:
# Create and bind listening socket
lsock = socket.socket()
lsock.bind(('', port))
lsock.listen(1)
while True:
csock, addr = lsock.accept()
print("Got connection from {}".format(addr))
# Start sub-process passing it the newly accepted socket as argument
subs = Process(target=start, args=(csock, ))
subs.start()
# Close our handle to the new socket (it will remain open in the
# sub-process which will use it to talk to the client)
csock.close()
# NOTE: do not call subs.join here unless you want the parent to *block*
# waiting for the sub-process to finish (and if so, what is the point in
# creating a sub-process?)
There are several others ways to do it as well: you can create multiple threads to handle multiple connections, or you can handle all connections in a single thread by using select or with asynchronous I/O.
The client is typically much simpler -- as it usually only cares about its own one connection -- and doesn't care which way the server is implemented:
sock = socket.socket()
sock.connect((ip, port))
while True:
sock.send(...)
sock.recv(...)
If the client does wish to connect to the same server again, it simply creates a second socket and call its connect method with the same server IP and port.
Usually, the client never needs to specify its own port, only the server's port. It simply calls connect and the client-side operating system chooses an unused port for it. So the first time, the client creates a socket and connects it (to the server's listening port), the client-side OS may choose port 50001. The next time it creates and connects a socket, it may get 50002 and so on. (The exact port numbers chosen depend on the operating system implementation and other factors, such as what other programs are running and creating connections.)
So, given client IP 192.168.0.101 and server IP 192.168.0.102, and assuming the server is listening on port 8000, this would result in these two connections:
(192.168.0.101/50001) ====> (192.168.0.102/8000)
(192.168.0.101/50002) ====> (192.168.0.102/8000)
I have a server that uses a thread to listen for new connections and then starts one thread for every client to serve him. Now, the server runs perfectly, but when a client connects it gives me the error in the title. I think because both client and server are trying to use the same port.
Here's the server code:
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
def __init__(self, conne):
initialization
def handle(self):# "run"
does something
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
HOST = '' # Symbolic name meaning all available interfaces
PORT = 1000 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
n=1
while 1:
conn, addr = s.accept() # wait for a new connection. Get a new socket (conn) for each new connection
print 'Connected by', addr
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) #this line gives me the error
ip, port = server.server_address
server_thread = threading.Thread(target=server.serve_forever)
server_thread.setDaemon(True)
server_thread.setName('Client '+str(n))
server_thread.start() # Start the new thread
n+=1
server.shutdown()
server.server_close()
And here's the client:
import socket
HOST, PORT = "localhost", 1000
data = "0"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
sock.sendall(data)
received = sock.recv(1024)
finally:
sock.close()
print "Sent: {}".format(data)
print "Received: {}".format(received)
First you create server socket and bind it to port 1000. Then when client connects you receive a socket connected with client (conn, addr = s.accept()) that should be used to communicate with client but you completely ignore it. Instead you create another server that tried to bind again to port 1000. This results in "already used" error as expected.
I'd suggest you check this example of TcpServer threading and forking. Here a custom class derived from SocketServer.TCPServer is created initially (not a simple server socket as you do). It internally loops over accepting incoming client connections and for each connection calls specified SocketServer.BaseRequestHandler from a new thread or process (in case of forking) so you don't need to deal with them explicitly. Custom request handler just needs to, well, handle the request, potentially in a loop if communication with client is multi-step.
Be aware that thread/process per client approach doesn't scale well on large number of simultaneous client connections.
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.