0

I need to test an application with more than 64K connections. I want to use the same host.

Today I start server that listents on 127.0.0.1 and connect to it from same machine, but of course it is limited to 64K connections.

I want to simulate a situation like I have one server and many clients connecting to a single server on specific single IP.

Server Listen: 1.2.3.4

Client Connect to 1.2.3.4 From 2.1.2.1
Client Connect to 1.2.3.4 From 2.1.2.2
Client Connect to 1.2.3.4 From 2.1.2.3
Client Connect to 1.2.3.4 From 2.1.2.4

So I need to setup a virtual network with multihoming so the client would be able to connect from several addressed and a server that listen on.

How can this be configured? On Linux?

Gareth Davis
  • 27,701
  • 12
  • 73
  • 106
Artyom
  • 31,019
  • 21
  • 127
  • 215
  • Add multiple IP addresses on a loopback; bind your application sockets to those addresses... is this hard? If so, what is the exact place where you are having difficulty? What have you tried so far? – Mike Pennington Jan 03 '13 at 09:37
  • I did `inet 127.0.0.1/8 scope host lo; inet 127.0.0.2/8 scope host secondary lo` however I still get all request from 127.0.0.1 even if I listen on "0.0.0.0" what do I miss – Artyom Jan 03 '13 at 09:43
  • TCP or UDP? I will show an example in Python, but you can generalize to whatever you're using – Mike Pennington Jan 03 '13 at 09:45
  • TCP, of course, and I need server configuration - i.e. how do I configure network interfaces. (The code works well) – Artyom Jan 03 '13 at 09:48

1 Answers1

0

Step 1: Add addresses to your loopback; I will add 10.0.0.1, 10.0.0.2, 10.0.0.3, 10.0.0.4 and 10.0.0.5 to lo

[mpenning@tsunami ~]$ ip addr show lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
[mpenning@tsunami ~]$ sudo ip addr add 10.0.0.1/24 dev lo
[mpenning@tsunami ~]$ sudo ip addr add 10.0.0.2/24 dev lo
[mpenning@tsunami ~]$ sudo ip addr add 10.0.0.3/24 dev lo
[mpenning@tsunami ~]$ sudo ip addr add 10.0.0.4/24 dev lo
[mpenning@tsunami ~]$ sudo ip addr add 10.0.0.5/24 dev lo
[mpenning@tsunami ~]$ sudo ip addr show lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet 10.0.0.1/24 scope global lo
    inet 10.0.0.2/24 scope global secondary lo
    inet 10.0.0.3/24 scope global secondary lo
    inet 10.0.0.4/24 scope global secondary lo
    inet 10.0.0.5/24 scope global secondary lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
[mpenning@tsunami ~]$

Step 2: Increase max connections

Step 3: Start lots of connections...

from socket import socket, AF_INET, SOCK_STREAM
import select

class Server(object):
    def __init__(self, addr="0.0.0.0", port=2525):
        self.listen_addr = addr
        self.listen_port = port
        self.server = socket(AF_INET, SOCK_STREAM)
        self.server.setblocking(0)
        self.server.bind(self.socket_tuple)
        self.server.listen(5)

    def __repr__(self):
        return "TCP Server listening on %s:%s" % (self.listen_addr,
            self.listen_port)

    @property
    def socket_tuple(self):
        return (self.listen_addr, self.listen_port)

    def close(self):
        self.server.close()

class Client(object):
    def __init__(self, addr="0.0.0.0"):
        self.listen_addr = addr
        self.server_addr = None
        self.server_port = None
        self.client = socket(AF_INET, SOCK_STREAM)
        self.client.setblocking(0)
        finished = False
        while not finished:
            try:
                ### The point of my answer is here...
                self.client.bind((addr,0)) # <- Bind to specific IP and rnd port
                finished = True
            except:
                pass

    def __repr__(self):
        return "TCP Client %s->%s:%s" % (self.listen_addr,
            self.server_addr, self.server_port)

    def connect(self, socket_tuple=("0.0.0.0",0)):
        self.server_addr = socket_tuple[0]
        self.server_port = socket_tuple[1]
        self.client.connect_ex(socket_tuple)

    def close(self):
        self.client.close()

READ_ONLY = select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR
clients = list()
servers = list()
for server_addr, port in [('10.0.0.1', 2525), ('10.0.0.2', 2526)]:
    ss = Server(addr=server_addr, port=port)
    servers.append(ss)
    for client_addr in ['10.0.0.3', '10.0.0.4', '10.0.0.5']:
        for ii in xrange(0, 25000):
            cc = Client(addr=client_addr)
            connection = cc.connect(socket_tuple=ss.socket_tuple)
            finished = False
            print "    %s conns" % len(clients)
            while not finished:
                poller = select.poll()
                poller.register(ss.server, READ_ONLY)
                # Map file descriptors to socket objects...
                fd_to_socket = {ss.server.fileno(): ss.server,}
                events = poller.poll(1)
                for fd, flag in events:
                    s = fd_to_socket[fd]
                    if flag & (select.POLLIN|select.POLLPRI):
                        if s is ss.server:
                            # server socket is ready to accept a connection
                            connection, client_address = s.accept()
                            connection.setblocking(0)
                            fd_to_socket[connection.fileno()] = connection
                            poller.register(connection, READ_ONLY)
                            finished = True
            clients.append(cc)
            print cc

print "Total Clients:", len(clients)
for cc in clients:
    cc.close()
for ss in servers:
    ss.close()

Adjust values above to your preferences... however, you should keep in mind that tuning a linux server to accept so many connections may be challenging... but at this point, that isn't the question you are asking...

Community
  • 1
  • 1
Mike Pennington
  • 41,899
  • 19
  • 136
  • 174