Server Bind:
A Server uses bind(3N) to establish the local host.port assignment -- ie. so it is the process behind that port. That's really only required for servers -- applications which accept(3N) connections to provide a service.
struct servent *sp;
struct sockaddr_in sin;
if ((sp=getservbyname(service,"tcp")) == NULL) then error...
sin.sin_family=AF_INET;
sin.sin_port=sp->s_port;
sin.sin_addr.s_addr=htonl(INADDR_ANY);
if ((s=socket(AF_INET,SOCK_STREAM,0)) < 0) then error...
if (bind(s, &sin, sizeof(sin)) < 0) then error...
htonl(3N) converts a long to the right sequence (given different byte ordering on different machines). The IP address INADDR_ANY means all interfaces. You could, if you wanted, provide a service only on some interfaces -- eg. if you only provided the service on the loopback interface (127.0.0.1) then the service would only be available to clients on the same system.
What this code fragment does is specify a local interface and port (into the sin structure). The process is bound to that port -- it's now the process behind the local port.
Client applications usually aren't concerned about the local host.port assignment (the connect(3N) does a bind o some random but unused local port on the right interface). But rcp(1) and related programs (like rlogin(1) and rsh(1)) do connect from reserved port numbers.
For example, the version of tcpopen.c used in the Passwdd/Passwd -- An authentication Daemon/Client. There's an instance where a client application connects from a reserved port.
Listen and Accept:
To accept connections, a socket is created with socket(3N), it's bound to a service port with bind(3N), a queue for incoming connections is specified with listen(3N) and then the connections are accepted with accept(3N) as in this fragment:
struct servent *sp;
struct sockaddr_in sin,from;
if ((sp=getservbyname(service,"tcp")) == NULL)
then error...
sin.sin_family=etc...
if ((s=socket(AF_INET,SOCK_STREAM,0)) < 0)
then error...
if (bind(s, &sin, sizeof(sin)) < 0)
then error...
if (listen(s,QUELEN) < 0) then error...
for (;;) {
if ((g=accept(f,&from,&len)) < 0)
then error...
if (!fork()) {
child handles request...
...and exits
exit(0);
}
close(g); /* parent releases file */
}
This is the programming schema used by utilities like sendmail(1M) and others -- they create their socket and listen for connections. When connections are made, the process forks off a child to handle that service request and the parent process continues to listen for and accept further service requests.
A Server uses bind(3N) to establish the local host.port assignment -- ie. so it is the process behind that port. That's really only required for servers -- applications which accept(3N) connections to provide a service.
struct servent *sp;
struct sockaddr_in sin;
if ((sp=getservbyname(service,"tcp")) == NULL) then error...
sin.sin_family=AF_INET;
sin.sin_port=sp->s_port;
sin.sin_addr.s_addr=htonl(INADDR_ANY);
if ((s=socket(AF_INET,SOCK_STREAM,0)) < 0) then error...
if (bind(s, &sin, sizeof(sin)) < 0) then error...
htonl(3N) converts a long to the right sequence (given different byte ordering on different machines). The IP address INADDR_ANY means all interfaces. You could, if you wanted, provide a service only on some interfaces -- eg. if you only provided the service on the loopback interface (127.0.0.1) then the service would only be available to clients on the same system.
What this code fragment does is specify a local interface and port (into the sin structure). The process is bound to that port -- it's now the process behind the local port.
Client applications usually aren't concerned about the local host.port assignment (the connect(3N) does a bind o some random but unused local port on the right interface). But rcp(1) and related programs (like rlogin(1) and rsh(1)) do connect from reserved port numbers.
For example, the version of tcpopen.c used in the Passwdd/Passwd -- An authentication Daemon/Client. There's an instance where a client application connects from a reserved port.
Listen and Accept:
To accept connections, a socket is created with socket(3N), it's bound to a service port with bind(3N), a queue for incoming connections is specified with listen(3N) and then the connections are accepted with accept(3N) as in this fragment:
struct servent *sp;
struct sockaddr_in sin,from;
if ((sp=getservbyname(service,"tcp")) == NULL)
then error...
sin.sin_family=etc...
if ((s=socket(AF_INET,SOCK_STREAM,0)) < 0)
then error...
if (bind(s, &sin, sizeof(sin)) < 0)
then error...
if (listen(s,QUELEN) < 0) then error...
for (;;) {
if ((g=accept(f,&from,&len)) < 0)
then error...
if (!fork()) {
child handles request...
...and exits
exit(0);
}
close(g); /* parent releases file */
}
This is the programming schema used by utilities like sendmail(1M) and others -- they create their socket and listen for connections. When connections are made, the process forks off a child to handle that service request and the parent process continues to listen for and accept further service requests.