I have a tcp server running that serves to two devices (clients). When I open the connection from a client and send data, I get the response as expected.
However, if I close the client connection and open again, I get "port already in use".
I am already setting socket.SO_REUSEADDR but there isn't the solution.
It is running into Linux Ubuntu.
import socket
import select
#!/usr/bin/python3
def main():
CONNECTION_LIST = [] # list of socket clients
RECV_BUFFER = 4096
PORT = 50001
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
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("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 received 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:
data = sock.recv(RECV_BUFFER)
print(data)
if data.startswith("CLIENT1_"):
sock.sendall("client1")
elif data.startswith("CLIENT2_"):
sock.sendall("client2")
# 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()
if __name__ == "__main__":
main()
I can only guess that you use Ctrl+C to stop server - but it raises error and script doesn't run server_socket.close(). And if it doesn't run server_socket.close() then socket is still open and SO_REUSEADDR can't change it.
You have to use server_socket.close() to close socket.
SO_REUSEADDR is only to release PORT after correct close. It only inform system that it has to release PORT at once after closing without blocking PORT for short time - but this need to close socket correctly.
So you need try/except or try/finally to run server_socket.close()
try:
server_socket = socket.socket(...)
# ... code ...
finally:
server_socket.close()
Related
Basically I have a chatroom which I'm going to turn into a network (I know it doesn't sound like it makes a lot of sense) but basically I was wondering if I could have a python script capture all outgoing requests on a computer and instead send it to another computer (c2). I then want c2 to make the request on it's own. This is a watered down explanation of what I'm doing but any help will be great!
Firstly, you can set up a remote machine and get its IP address. On the remote machine you can set up this code:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('*CHANGE TO SERVER IP*', portnumber)
print("Starting on %s port %s" % server_address)
sock.bind(server_address)
sock.listen(1)
while True:
connection, client_address = sock.accept()
try:
data = connection.recv(999)
# You have received the data, do what you want with it.
except:
connection.close()
And on the client machine:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('*INSERT SERVER IP*', portnumber)
print('Connecting to %s port %s' % server_address)
while True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(server_address)
message=input('Message: ')
if message=='quit':
break
sock.sendall(message)
except:
break
sock.close()
The server side code also works as client side for receiving information.
I am making a socket Chat server in python 2.7 but I am unable to connect to the server using my client I get this error:
File "ChatClientV2.py", line 46, in
read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])
select.error: (10038, 'An operation was attempted on something that is not a socket')
I do not know why i am getting this error I need to help with this this is my code I use for the client and some extra stuff after but I do not want to be restricted by the code amount so I did not post all of it
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 ?
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("192.168.0.8", 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:
#print CONNECTION_LIST
# 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, "entered room\n")
#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()
Before you say this is a duplicate, I have looked at many articles on this and still can't fix it.
I am making a very basic chat client and server python program.
However after connecting through my client, it says 'Connected' on the server console, but disconnects immediately on the chat one with the error 'OSError: [WinError 10038] An operation was attempted on something that is not a
socket'
CHAT
def chat_client():
if(len(sys.argv) not in (3, 4)):
print("Usage: python chat_client.py <hostname> <port> <optional-username>\n")
sys.exit()
host = sys.argv[1]
port = int(sys.argv[2])
username = ""
if len(sys.argv) == 4:
username = sys.argv[3]
else:
username = "Guest"
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. You can start sending messages")
print("*** Press Control-C to log off ***\n")
sys.stdout.write("[" + username + "] ")
sys.stdout.flush()
while True:
socket_list = [sys.stdin, s]
try:
# Get the list sockets which are readable
ready_to_read, ready_to_write, in_error = select.select(socket_list, [], [])
except KeyboardInterrupt:
system("clear")
sys.stdout.write("\nYou have logged off\n")
sys.stdout.flush()
sys.exit()
SERVER
HOST = ""
SOCKET_LIST = []
RECV_BUFFER = 4096
PORT = 9009
CONVERSATION = ""
def chat_server():
global CONVERSATION
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
# Add server socket object to the list of readable connections
SOCKET_LIST.append(server_socket)
print("Chat server started on port " + str(PORT))
while True:
try:
# Get the list sockets which are ready to be read through select
# 4th arg, time_out = 0 : poll and never block
ready_to_read, ready_to_write, in_error = select.select(SOCKET_LIST, [], [], 0)
for sock in ready_to_read:
# A new connection request recieved
if sock == server_socket:
sockfd, addr = server_socket.accept()
SOCKET_LIST.append(sockfd)
print("Client (%s, %s) connected" % addr)
broadcast(server_socket, sockfd, "[%s, %s] entered our chatting room\n" % addr)
# A message from a client, not a new connection
else:
# Process data recieved from client
try:
# Recieving data from socket
data = sock.recv(RECV_BUFFER)
if data:
# there is something in the socket
# broadcast(server_socket, sock, "\r" + '[' + str(sock.getpeername()) + '] ' + data) # old
broadcast(server_socket, sock, "\r" + data)
else:
# Remove the socket that's broken
if sock in SOCKET_LIST:
SOCKET_LIST.remove(sock)
# at this stage, no data probably means the connection has been broken
broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
except:
broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
continue
except KeyboardInterrupt:
server_socket.close()
sys.exit()
server_socket.close()
# broadcast chat messages to all connected clients
def broadcast(server_socket, sock, message):
for socket in SOCKET_LIST:
# send the message only to peer
if socket != server_socket and socket != sock:
try:
socket.send(message)
except:
# Broken socket connection
socket.close()
# Broken socket, remove it
if socket in SOCKET_LIST:
SOCKET_LIST.remove(socket)
if __name__ == "__main__":
sys.exit(chat_server())
From select's documentation:
File objects on Windows are not acceptable, but sockets are. On
Windows, the underlying select() function is provided by the WinSock
library, and does not handle file descriptors that don’t originate
from WinSock.
This rules out using sys.stdin.
Alternatives:
Use Cygwin (No modifications to code needed)
Create a thread that waits on sys.stdin (like here)
Go the full Windows route and use WaitForMultipleObjects
Use some library that abstracts these details away, I like libuv but haven't used it with python
Another thing: Don't use select with a zero timeout in an infinite loop. This busy waiting is really inefficient. Instead omit the timeout to have select block till a descriptor becomes ready.
I'm trying to create a chatroom based on sockets which works on windows.
I have a server script:
# chat_server.py
import sys
import socket
import select
HOST = ''
SOCKET_LIST = []
RECV_BUFFER = 4096
PORT = 9009
def chat_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
threads = []
#add server socket object to the list of readable connections
SOCKET_LIST.append(server_socket)
print("Chat server started on port " + str(PORT))
while 1:
# get the list sockets wich are ready to be read through select
# 4th arg, tiome_out = 0 : poll and never block
ready_to_read,ready_to_write,in_error = select.select(SOCKET_LIST,[],[],0)
for sock in ready_to_read:
# a new connection request recieved
if sock == server_socket:
sockfd, addr = server_socket.accept()
SOCKET_LIST.append(sockfd)
print("Cient (%s, %s) connected" % addr)
broadcast(server_socket, sockfd, "[%s:%s] entered our chatting room\n" % addr)
# a message from a client, not a new connection
else:
# process data recieved from client,
try:
#receiving data from the socket.
data, addr = sock.recvfrom(RECV_BUFFER)
if data:
# there is something in the socket
broadcast(server_socket, sock, "\r" + '[' + str(sock.getpeername()) + ']' + data)
else:
# remove the socket that's broken
if sock in SOCKET_LIST:
SOCKET_LIST.remove(sock)
# at this stage, no data means probably the connection has been broken
broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
# exception
except:
broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
continue
server_socket.close()
# broadcast chat messages to all connected clients
def broadcast (server_socket, sock, message):
for socket in SOCKET_LIST:
# send the message only to peer
if socket != server_socket and socket != sock :
try :
socket.send(message)
except :
# broken socket connection
socket.close()
# broken socket, remove it
if socket in SOCKET_LIST:
SOCKET_LIST.remove(socket)
if __name__ == "___main__":
sys.exit(chat_server())
chat_server()
And a client script:
# chat_client.py
import sys
import socket
import select
from threading import Thread
def chat_client():
if(len(sys.argv) < 3):
print('Usage: python chat_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. You can start sending messages')
sys.stdout.write('[Me] '); sys.stdout.flush()
sock_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_send.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock_send.bind((host, port))
def send_msg(sock):
while True:
# user entered a message
s.send(sys.stdin.buffer.readline())
sys.stdout.write('[Me] '); sys.stdout.flush()
def recv_msg(sock):
while True:
# incoming message from remote server, s
data, addr = sock.recvfrom(1024)
if not data :
print('\nDisconnected from chat server')
sys.exit()
else:
#print data
sys.stdout.write(data)
sys.stdout.write('[Me] '); sys.stdout.flush()
Thread(target=send_msg, args=(sock_send,)).start()
Thread(target=recv_msg, args=(sock_send,)).start()
if __name__ == "__main__":
sys.exit(chat_client())
The program is executed with:
$ python chat_server.py
$ python chat_client.py localhost 9009
If I run the code I won't get any Error. When I run several clients at the same time they all connect to the server correctly, but one client doesn't get the text another client has written.
I think something is wrong with the server's broadcast function, but I'm not sure what it is.
I already searched for similar questions, but I didn't find anything useful for fixing this problem. Please Help!
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)