We were given an assignment in one of our classes to write a port scanner. This was a great assignment and we've learn't a lot from it. The assignment was pretty huge with lot of functions. For those of you who don't know what a port scanner is, a port scanner is a piece of software that can be used to determine the status of network ports in a given machine. A port scanner can also be used to determine what are the software running on open ports etc. Ports are specific to
TCP and
UDP and a port scanners functionality is border than TCP and UDP and can be used to determine the protocols that are running in machines etc. A good place to look at for more details is
here. For making our discussion simple lets assume we are only going to scan TCP ports.
One of the key things about a port scanner is the ability to scan ports in parallel. Usually there are 2 to the power 16 ports in a given machine. But usually we want to scan a subset of these ports and even this subset can be huge. So if we scan each port one by one it will take a lot of time. To avoid this we have to send requests in parallel to the range of ports that we scan.
A port scanning request for the most part is an IP packet with a TCP or UDP payload. In the TCP case we don't want to create a full TCP connection in order to determine weather the port is open. We can simply send a TCP SYN packet and if we get a response with SYN + ACK we can conclude that the port is open. There are many other techniques for determining the status of a port and non of them require us to create a connection. To send these TCP SYN packets we need to use RAW Sockets and we cannot use regular stream sockets.
The important summery of the above is that we create a TCP SYN packet for each port that we are going to scan and send them in parallel to the destination IP using a
RAW Socket.
Since these are RAW sockets there is no TCP
Flow Control or TCP
Congestion control. Once we call the
send with the IP packet, the kernel will send the packet as fast as it can. First it will copy the buffer to the kernel space and hand over this to the IO Subsystem to send. The important thing is the call to send the packet is non blocking on IO as we are not waiting for the success or failure of this packets to be delivered to the destination or out of the host machine. But since send involves a system call it can be bit slow compared to other method calls. Also note that these are very small packets, with byte sizes no more that 50 bytes for the IP packet and there is no data in the TCP packet.
The assignment asked us to create threads for making the sending process parallel. The expectation is that as the number of threads increases the sending speed will increase. But is this really true?
Will threads increase the sending performance linearly?
If we run the program on a multi-core machine definitely the increase of threads should increase the sending rate until the number of threads is somewhat greater than the available processors. But will this increase the performance if we increase the number of threads to 100 and available processes is 8? My gut feeling is it
NO. But people tend to think that increasing the number of threads will increase the rate of sending. But since the operations are CPU bound increasing the number of threads beyond the number of available cores is not going to give any performance. On the contrary increasing the threads should decrease the performance of the system.
This is a conclusion I came from theoretical knowledge and past experiences. No performance test was done. may be I should do a performance test or may be I should not :) Lets see what others have to say.
View comments