Basic server communication is established as follows:
The socket() call in Perlwill look something like this (basic_socket.p):
$tcpProtocolNumber = getprotobyname('tcp') || 6; socket(SOCKET, PF_INET(), SOCK_STREAM(), $tcpProtocolNumber) || die("socket: $!");
The first line gets the TCP protocol number using the getprotobyname() function. Some systems (e.g. Windows 95) do not implement this function, so a default value of 6 is provided. Then, the socket is created with socket().
The socket name is SOCKET.
Notice that it looks just like a file handle. When creating your own sockets, the first parameter is the only thing that you should change. The rest of the function call will always use the same last three parameters shown above. The actual meaning of the three parameters is unimportant at this stage. If you are curious, please refer to the UNIX documentation previously mentioned.
Socket names exist in their own namespace. Actually, there are several pre-defined namespaces that you can use. The namespaces are called protocol families because the namespace controls how a socket connects to the world outside your process. For example, the PF_INET namespace used in the socket() function call above is used for the Internet.
Once the socket is created, you need to bind it to an address with the bind() function.
The bind() call might look like this (bind.pl):
$port = 20001; $internetPackedAddress = pack('Sna4x8', AF_INET(), $port, "\0\0\0\0"); bind(SOCKET, $internetPackedAddress) ||die("bind: $!");
All Internet sockets reside on a computer with symbolic names. The server's name in conjunction with a port number makes up a socket's address. For example, www.cs.cf.ac.uk:20001. Symbolic names also have a number equivalent known as the dotted decimal address. For example, 22.214.171.124. Port numbers are a way of determining which socket at www.cs.cf.ac.uk you'd like to connect to. All port numbers below 1024 (or the symbolic constant, IPPORT_RESERVED) are reserved for special sockets. For example, port 37 is reserved for a time service and 25 is reserved for the smtp service. The value of 20,001 used in this example was picked at random. The only limitations are: use a value above 1024 and no two sockets on the same computer should have the same port number.
Remember: You can always refer to your own computer using the dotted decimal address of 127.0.0.1 or the symbolic name localhost.
The second line of this short example creates a full Internet
socket address using the pack()
function. This is another complicated topic that I will sidestep.
As long as you know the port number and the server's address,
you can simply plug those values into the example code and not
worry about the rest. The important part of the example is the
\0" string. This string holds the four numbers
that make up the dotted decimal Internet address. If you already
know the dotted decimal address, convert each number to octal
and replace the appropriate
\0 in the string.
If you know the symbolic name of the server instead of the dotted decimal address, use the following line to create the packed Internet address:
$internetPackedAddress = pack('S n A4 x8', AF_INET(), $port, gethostbyname('www.remotehost.com'));
After the socket has been created and an address has been bound to it, you need to create a queue for the socket. This is done with the listen() function.
The listen() call looks like this:
listen(SOCKET, 5) || die("listen: $!");
This listen() statement will create a queue that can handle 5 remote attempts to connect. The sixth attempt will fail with an appropriate error code.
Now that the socket exists, has an address, and has a queue, your program is ready to begin a conversation using the accept() function. The accept() function makes a copy of the socket and starts a conversation with the new socket. The original socket is still available and able to accept connections. You can use the fork() function, in UNIX, to create child processes to handle multiple conversations. The normal accept() function call looks like this:
$addr = accept(NEWSOCKET, SOCKET) or die("accept: $!");
Now that the conversation has been started, use print(), send(), recv(), read(), or write() to hold the conversation. The examples later in the chapter show how the conversations are held.