I had an exercise of port carousel which means that I need to build a server-client which the server asks the client for a port and then they starting to listen to the port that given, and this is the loop I got a error and I don't know how to fix it.
server:
import socket
import random
def main():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 1729))
server_socket.listen(1)
(client_socket, server_socket) = server_socket.accept()
done = False
while not done:
port = client_socket.recv(4096)
client_socket.send('i got the port' + port)
port = int(port)
if port != 1:
server_socket.bind(('0.0.0.0', port))
continue
else:
done = True
if __name__ == '__main__':
main()
client:
import socket
import random
def main():
print 'hi at anytime enter 1 to break the loop'
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 1729))
done = False
while not done:
port = client_socket.send(raw_input("enter port:"))
data = client_socket.recv(4096)
print data
port = int(port)
if port != 1:
client_socket.connect(('127.0.0.1', port))
continue
else:
done = True
client_socket.close()
if __name__ == '__main__':
main()
the error output for the server:
File "C:/Cyber/ServerFolder/ports_carrousel.py", line 18, in main
server_socket.bind(('0.0.0.0', port))
AttributeError: 'tuple' object has no attribute 'bind'
In your main function, you do the following:
(client_socket, server_socket) = server_socket.accept()
but, server_socket.accept() actually returns two objects. The first, is a socket object, and the second one is a tuple that contains (sourceIPString, sourcePort).
Thus, by using this line of code, outlined above, you are essentially overriding the server_socket by a tuple object.
Notice that later, in line 18, you are trying to access the "bind" function of a socket, but, using a reference to a tuple object, that does not implement such a function.
What you should be doing is something along the lines of
(client_socket, client_connection_info) = server_socket.accept()
and adjust your code accordingly.
Just a couple of things wrong here. First, accept returns a 2-tuple containing the newly-connected socket, and the client's address (which is itself a 2-tuple of IP address and port number). It does not return two sockets. But you're overwriting your server_socket variable with the second returned value. That doesn't make sense and it's why the interpreter is telling you that the 2-tuple has no bind attribute: it's not a socket object. The accept call should look something like this:
client_socket, client_addr = server_socket.accept()
Next, after receiving the new port number from the client, you must create a new socket (you cannot re-use the same listening socket), then bind that new socket to the new port, then listen; finally you can accept a new client connection from the new listening socket.
You should also close sockets you're finished with so that you don't continually leak file descriptors. That means each time you receive a new port number from the client, you should close the client socket, and the listening socket, then create a new listening socket (and bind and listen), then accept the new client socket.
Altogether that will mean restructuring your code in the server significantly. You need to pull the creation of a listening socket down into your main while not done loop.
Another thing to keep in mind. On the client side, immediately after sending the port number to the server, you're attempting a connect to that new port number. However, it's almost certain that your connect request will reach the server before the server has had a chance to create a new listening socket, and bind it. So your client will either need to delay a moment before attempting to connect, or it will need to have logic to retry the connect for some period of time.
EDIT:
Also, you must create a new socket on the client side too when reconnecting. Once a stream socket has been bound to a port (which also happens automatically when you connect), you can never use it to bind or connect to a different address/port.
Related
I'm building a Client-Server connection for an assignment. The server basically runs everything and the client only receives messages from the server and responds when the server needs it to.
For some reason, I can't build a client that repeatedly listens and then responds.
I thought that I could just listen with socket.recv() and it ended up just stopping everything.
this is what I ended up with after some tweaking (for the client) :
import socket
HOST = 'localhost'
PORT = 65432
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((HOST, PORT))
conn.setblocking(False)
while True :
try :
msg_lgn = len(conn.recv(1024,socket.MSG_PEEK))
server_message = conn.recv(1024).decode()
print('Server Sent:\n' + server_message)
if server_message == 'exit':
break
except :
conn.send(input().encode())
conn.close()
I set it to non-blocking so it won't hang on the conn.recv() and move on to input in the exception, but then it just freezes on the input.
does the server close the connection every time recv() gets nothing ? why is this happening ?
I just want the client to receive messages whenever the server sends them, and when the server doesn't send, the client will send the server it's input.
would appreciate any help!
Lidor
Edit : the server file is much bigger, so i'll show the important parts.
#imported some classes for the game itself also (that i've created), but has nothing to do with the problem
import socket
import time
import threading
def startGame(conn):
#this is where the servers sends the questions and receives answer (pretty basic send and recv)
# Establish Client-Server Connection
HOST = 'localhost' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(3)
# Use Threading to start the game for an new player
while True:
if playerCount < 3:
(conn, addr) = s.accept()
playerCount += 1
x = threading.Thread(target=startGame, args=(conn,))
x.start()
# Close Server Socket
s.close()
I want to create a multiprocessing echo server. I am currently using telnet as my client to send messages to my echo server.Currently I can handle one telnet request and it echos the response. I initially, thought I should intialize the pid whenever I create a socket. Is that correct?
How do I allow several clients to connect to my server using multiprocessing.
#!/usr/bin/env python
import socket
import os
from multiprocessing import Process
def create_socket():
# Create socket
sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Port for socket and Host
PORT = 8002
HOST = 'localhost'
# bind the socket to host and port
sockfd.bind((HOST, PORT))
# become a server socket
sockfd.listen(5)
start_socket(sockfd)
def start_socket(sockfd):
while True:
# Establish and accept connections woth client
(clientsocket, address) = sockfd.accept()
# Get the process id.
process_id = os.getpid()
print("Process id:", process_id)
print("Got connection from", address)
# Recieve message from the client
message = clientsocket.recv(2024)
print("Server received: " + message.decode('utf-8'))
reply = ("Server output: " + message.decode('utf-8'))
if not message:
print("Client has been disconnected.....")
break
# Display messags.
clientsocket.sendall(str.encode(reply))
# Close the connection with the client
clientsocket.close()
if __name__ == '__main__':
process = Process(target = create_socket)
process.start()
It's probably a good idea to understand which are blocking system calls and which are not. listen for example is not blocking and accept is blocking one. So basically - you created one process through Process(..), that blocks at the accept and when a connection is made - handles that connection.
Your code should have a structure - something like following (pseudo code)
def handle_connection(accepted_socket):
# do whatever you want with the socket
pass
def server():
# Create socket and listen to it.
sock = socket.socket(....)
sock.bind((HOST, PORT))
sock.listen(5)
while True:
new_client = sock.accept() # blocks here.
# unblocked
client_process = Process(target=handle_connection, args=(new_client))
client_process.start()
I must also mention, while this is a good way to just understand how things can be done, it is not a good idea to start a new process for every connection.
The initial part of setting up the server, binding, listening etc (your create_socket) should be in the master process.
Once you accept and get a socket, you should spawn off a separate process to take care of that connection. In other words, your start_socket should be spawned off in a separate process and should loop forever.
I'm learning about sockets and connections and trying to write a simple server Python script that echos a message to a client.
I began with just running a script that prints what it receives from a socket.
So i'm running what i wrote locally and using Putty as a client (so the message isn't printed to the putty session yet).
This is my code:
import socket
HOST = '127.0.0.1'
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT)) # bind accepts a tuple of a hostname or address and a port
s.listen()
conn, addr = s.accept() # returns a pair
with conn:
print("Connection started!", conn, addr)
data = conn.recv(1024)
while data:
data = data.decode("UTF-8")
print(data)
# if data == "exit":
# shutdown and close the connection,
# and ofcourse exit the two with as blocks gracefully
data = conn.recv(1024)
print("Connection is closed and the program continued")
Running this works but i have no way of terminating the connection other then killing the server.
I believe that data will always be true since i'm using putty and it seems that even when i'm hitting enter with no text to the connection window, it actually sends this:
b'\r\n'
So I tried placing this inside the commented if statement:
conn.shutdown(socket.SHUT_RDWR)
conn.close()
Hoping this will just make the socket be deleted - but it didn't work.
So what I want to do is to exit the with blocks and deleting the sockets without having to raise any exceptions or make the program stop. I tried doing so using python 3 change to socket that made it usable with with-as statements. I tried just calling the conn.__exit__ or s.__exit__ function but that didn't work also.
How can I close the socket and exit the two with blocks using an input from the user? Is there anything i'm confusing with the socket module here?
I am have recently been learning about networking. So I tried doing an experiment I found on the web. It was a simple server client connection. But I got this error when I tried running my server.py:`
TypeError: Can't convert 'builtin_function_or_method' object to str implicitly
This is the code for server.py:
import socket # socket module
s = socket.socket() # creates socket object "s"
host = socket.gethostname # gets name of local pc
port = 5567 # Reserve a port for the service (numbers are random)
s.bind((host, port)) # connects our host and port number to our socket
s.listen(5) # waits for client connection (5 maximum connections)
while True: # repeats forever
c, addr = s.accept # Establishes connectd from anyone who tries to connect (c is client object)
print('Got connection from, '+ addr ) # prints on server gui its connection
c.send('Thank you for connecting!') # sends client message
c.close() # stops all connection to current client
The error was on line 6.
Thank you in advance.
You are forgetting to call your functions:
host = socket.gethostname # gets name of local pc
and
c, addr = s.accept # Establishes connectd from anyone who tries to connect (c is client object)
Both socket.gethostname and s.accept are callables, add ():
host = socket.gethostname()
and
c, addr = s.accept()
The exception you see is caused by you passing in the socket.gethostname function rather than what the function produces.
I need to make a program that communicates within the same program back and forth between client and server, but after following the instructions on: http://woozle.org/~neale/papers/sockets.html it just keeps listening and I see nothing printed.
How do I enable basic client server functionality within the same file?
#!/usr/bin/python # This is server.py file
import socket # Import socket module
import random
import os
import time as t
#open socket
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = random.randint(0,65535) # Reserve a port for your service.
if os.fork() == 0:
#server
s.listen(1)
print 'about to listen'
while 1:
c = s.accept()
cli_sock, cli_addr = c
cli_sock.send("Hello to you! %s" % cli_addr)
elif os.fork() == 0:
t.sleep(1)
#client
print 'in here2'
s.bind((host, port)) # Bind to the port
s.connect((host,port))
s.send("Hello!\n")
print s.recv(8192)
s.close()
You're never going to hit your client code, as you enter an infinite loop right after starting the listener. For a toy example like this, you'll need to create 2 socket objects, one for the server and one for the client, then pingpong back and forth between them within your code; you can't use a serve forever style loop like you are here unless it runs in a parallel thread/process so you don't block execution of the main thread.