How to make a socket server that only accepts one connection? - python

I write a TCP server using Python. I want the server
only accept on client connection.
I use the listen function
listen(1)
but the server still can accepts more than one connection.

From the documentation:
If backlog is specified, it must be at least 0 (if it is lower, it is set to 0); it specifies the number of unaccepted connections that the system will allow before refusing new connections.
So if you use listen(1) you allow one unaccepted connection. If you want to allow no unaccepted connections, you must use listen(0).

If you want only one connection, pleae don't use loop for socket.accept() in- connections.
demo code:
#!/usr/bin/python
import time
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_addr = ('127.0.0.1', 8080)
server.bind(server_addr)
server.listen(1)
print("listening on {}".format(server_addr))
client, client_addr = server.accept()
for i in range(10):
client.send("num: {}\n".format(i))
time.sleep(1)
raw_input('')

Related

UDP broadcast and automatic server discovery in python, TCP socket unavailable

I'm developing a reverse shell application in python, and right now I'm trying to implement an autodiscovery feature. It should work as follows:
The server broadcasts the IP/port it listens for connections on, and waits for a client. If no client tries to connect in a few seconds, it broadcasts again (and repeat till a connection).
The client tries to receive the broadcast of the server, and connects to the advertised IP/port.
The broadcast works fine, the client receives the IP/port and successfully connects, however after using the connected pair of ports I get (server side):
socket.error: [Errno 35] Resource temporarily unavailable
Server side test code:
sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sckt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sckt.settimeout(2)
sckt.bind(('', 9999))
sckt.listen(5)
broadcastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
while True:
broadcastSocket.sendto(socket.gethostbyname(socket.getfqdn()) + ' ' + str(9999), ('<broadcast>', 8888))
try:
sock, address = sckt.accept()
break
except socket.timeout:
pass
broadcastSocket.close()
sckt.settimeout(None)
sock.send('test')
# if I add time.sleep(1) here, it works, but I don't get why
# would sock be unavailable at first, but available a second later
print sock.recv(1) # this is where it fails
# note that it also fails with any recv buffer size, for instance 1024
Why on earth would I want to receive 1 byte of data, you might ask. I have an algorithm which prefixes messages with their lengths, and the receiver reads this prefix byte-by-byte till a delimiter, thats why.
Client side test code:
broadcastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
broadcastSocket.settimeout(3)
broadcastSocket.bind(('', 8888))
while True:
try:
data = broadcastSocket.recv(1024)
break
except socket.timeout:
pass
broadcastSocket.close()
sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sckt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sckt.connect((str(data.split()[0]), int(data.split()[1])))
print sckt.recv(1024)
sckt.send('lel')
If I omit the whole broadcast and autodiscovery part of the code and simply manually enter the IP/port of the server print sock.recv(1) doesn't fail.
Any clues on what the issue might be?
Change sckt.settimeout(None) to sock.settimout(None) in the server code.
You want to have the accepted socket in blocking mode and not the accepting one.
This ensures that the sckt.recv waits for an incoming message from the client.
P.S.
sock.setblocking(1) is exactly the same

Python TCP several listen on several ports at once

I'm building a python server that basically has a bunch of ports listening for connections. when a connection is made, the port spits out a message, closes the connection and , resets (ie waits for the next connection).
desired function:
create TCP socket for each port in portlist (this is dynamically populated via arguments)
listen for connection
when a connection made, send message, and disconnect
continue to listen
I have a feeling that my answer may ly in multi threading, but I'm not sure...My code so far:
for port in portlist:
ds = ("0.0.0.0", port)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(ds)
server.listen(1)
while 1:
connection, address = server.accept()
message="message\n"
connection.send(message)
connection.close()
There is single-threaded approach (on the listening side anyway - actually handling the connections may still require multiple threads).
You should open all of your sockets up-front, and put them in a list.
Then, you should select on all of them, which will return when any one of them is ready to be accepted on.
Something like this (totally untested):
servers = []
for port in portlist:
ds = ("0.0.0.0", port)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(ds)
server.listen(1)
servers.append(server)
while True:
# Wait for any of the listening servers to get a client
# connection attempt
readable,_,_ = select.select(servers, [], [])
ready_server = readable[0]
connection, address = ready_server.accept()
# Might want to spawn thread here to handle connection,
# if it is long-lived

python socket connecting to different subnet/domain

Is it possible to connect to a different subnet or domain by python socket programming?
I want to make a script for sharing files with friends,, but currently I only know how to
connect within one LAN.
in LAN, you should broadcast packets to discover each other.
and every peer should listen the port to receive broadcast.
It is discovery protocol, you can implement it by UDP socket.
Once two peer decide to communicate, they should create a TCP socket. Then, they can send data via TCP.
Or you can use HTTP, XML-RPC etc. to transfer data(not broadcast, TCP is not support broadcast).
#udp broadcast
import socket, time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
while True:
data = 'test'.encode()
s.sendto(data, ('255.255.255.255', 1080))
time.sleep(1)
#udp receive broadcast
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 1080))
while True:
print(s.recv(1024))

Sharing UDP broadcast reception -- python example

I have a UDP broadcast of some data. I'm able to open the following client in python 2.6.1, under OSX 10.6.8, and it works. I can catch the data, all is well.
But: this code "consumes" the port, in that I can't open another one, the 2nd attempt to bind fails... and I must allow for more than one listener. Here's the code that opens the port:
import select, socket
port = 58083 # port msg is broadcast upon
# Create listening port
# ---------------------
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.bind(('', port))
except:
print 'failure to bind'
s.close()
raise
s.setblocking(0)
...Since UDP is intended for broadcast to multiple clients (among other things), I assume I'm doing something wrong. I just can't figure out what.
I found an example on activestate that suggested:
s.bind(('<broadcast>',port))
...but that simply fails every time. Binding to 0.0.0.0 works, but also suffers from the "one client" problem. Binding to the local IP (e.g. 192.168.1.100) doesn't work at all. Removing the bind doesn't work at all.
Anyone?
If you need multiple processes to listen on 58083, you need to set SO_REUSEADDR on the socket before socket.bind()
import select, socket
port = 58083 # port msg is broadcast upon
# Create listening port
# ---------------------
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Allow other processes to
# bind to port
try:
s.bind(('0.0.0.0', port))
except:
print 'failure to bind'
s.close()
raise
s.setblocking(0)
After adding an infinite loop at the bottom, and running this twice on my linux server (once as root, and the other as unpriv user), I see:
root#tsunami# lsof | grep 58083
python 25908 root 3u IPv4 284835 0t0 UDP *:58083
python 25945 mpenning 3u IPv4 284850 0t0 UDP *:58083
root#tsunami#

Sending a reset in TCP/IP Socket connection

I am using python’s socket.py to create a connection to an ftp-server. Now I want to reset the connection (send a RST Flag) and listen to the response of the ftp-server. (FYI using socket.send('','R') does not work as the OS sends FIN flag instead of RST.)
Turn the SO_LINGER socket option on and set the linger time to 0 seconds. This will cause TCP to abort the connection when it is closed, flush the data and send a RST. See section 7.5 and example 15.21 in UNP.
In python:
def client(host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
s.connect((host, port))
l_onoff = 1
l_linger = 0
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
struct.pack('ii', l_onoff, l_linger))
# send data here
s.close()
If you want to implement your own behavior over connections I think you should try using Scapy. It is a really useful library/tool. It lets you play with IP/TCP/UDP/ICMP packages.
To send an RST on a TCP connection, set the SO_LINGER option to true with a zero timeout, then close the socket. This resets the connection. I have no idea how to do that in Python, or indeed whether you can even do it.

Categories

Resources