Thu 19 Oct 2006
TCP/IP SOCKET_LIST[FD_SETSIZE] = 200
Posted by datacrush under Techs
TCP/IP socket programming is a forgotten art. Thanks to simplified APIs, any Dumb and Dumber character can code something that works like a chimp.
If you’ve written TCP/IP socket server in C language on iSeries before, you would have encountered that FD_SETSIZE == 200. You would also realized that you’d typically declare socket_list[FD_SETSIZE], thus limiting the number of maximum concurrent handling to 199 clients (1 for the server) at any given time within a job.
And also, you would have realized that only a single job could bind to a specific IP and port at any given time. So it appears to be that only 200 concurrent connections may be active for a particular IP and port.
This led many to believe the only way around it is to open more server ports, albeit the potential security threat that it pose to the system.
Java-only programmers don’t understand this problem. They’ve been exposed to methods and procedures so simple that a primate could teach a caveman to use. All one needs to code in Java, for example:
ServerSocket server = new ServerSocket(localPort);
Socket client = null;
try {
…client = server.accept();
…ClientHandling ch = new ClientHandling(client);
…ch.start();
}
Assume ClientHandling is the actual piece of code that handles socket read and write. Therefore, have ClientHandling coded to handle each connected client in a separate thread of its own, for example:
class ClientHandling extends Thread {
…public void run() {
……byte[] request = read(client.getInputStream(), n);
……write(client.getOutputStream(), byte[] response);
…}
}
Starting a new thread is not exactly the same as starting a new job (process). Threads and processes are two different things, but by taking this as an example, I want to show you how you too can make use of similar concept in ILE C.
The solution in overcoming the number 200 is to start multiple server jobs, but not multiple ports. We only need to set one server job as a master and the rest as slaves.
The master server is the only one to perform the following lines of code:
rc = bind(listen_sd, (struct sockaddr *)&serveraddr, ………….sizeof(serveraddr)); rc = listen(sock_server, SOMAXCONN)); rc = accept(listen_sd, (struct sockaddr *)&clientaddr, len);
A master server binds on the listening port, accepts incoming connection and passes on the socket descriptor to a pool of slave jobs. One of the slave jobs inherits the connection and continues to perform socket receive and send as per normal.
The FD_SETSIZE limit is only within a job, not port. This method allows virtually unlimited clients on a single server port.
This can be done using givedescriptor and takedescriptor procedure.
rc = givedescriptor(*sock_desc, intjobid); *sock_desc = takedescriptor(NULL);
In the code snippet above, give and take is in two separate jobs; the first executed in the master server and the second in the slave server.
The master performs socket descriptor transfer to one of the slaves using internal job identifier, which is retrievable using QUSRJOBI API like the following:
QUSRJOBI(&jobinfo, sizeof(jobinfo), "JOBI0100", "*", " ", &error);
After receiving the client’s socket descriptor from the master, the slave can proceed to perform whatever routine that normally occurs after accept() procedure. In my case, to add the client to an array for listening, like the following:
socket_list[++connected] = *sock_desc;
Now that we’ve got a master server as an incoming connection gateway, and a pool of slave servers without an external IP binding to perform client handling, realize that each slave is able to handle at least 200 socket descriptors. That’s 200 more potential concurrent connections per job!
Of course, the slave job has got to execute select() function in order to work with multiple client’s socket descriptors. For example:
max = 0;
for (i = 0; i <= connected; i++) {
…if (socket_list[i] >= max) max = socket_list[i];
…FD_SET(socket_list[i], &read_fd);
}
max++;
rc = select(max, &read_fd, NULL, NULL, &timeout);
When I first brought this up in my company a few years ago, it was a revelation to many. Of course, they’re all cave dwellers so any new technology either amuses them or scares them. Anything unfathomable becomes symmetrical and anything contradictory to their argument becomes asymmetrical.
More information on socket programming can be found on IBM website. With programming interface made simple, sockets shouldn’t be so hard.