Explore topic-wise InterviewSolutions in .

This section includes InterviewSolutions, each offering curated multiple-choice questions to sharpen your knowledge and support exam preparation. Choose a topic below to get started.

51.

What Is The Difference Between Close() And Shutdown()?

Answer»

Generally the difference between CLOSE() and shutdown() is: close() closes the socket id for the process but the connection is still OPENED if another process shares this socket id. The connection stays opened both for read and WRITE, and sometimes this is very important. shutdown() BREAKS the connection for all processes sharing the socket id. Those who TRY to read will detect EOF, and those who try to write will reseive SIGPIPE, possibly delayed while the kernel socket buffer will be filled. Additionally, shutdown() has a second argument which denotes how to close the connection: 0 means to disable further reading, 1 to disable writing and 2 disables both.

Generally the difference between close() and shutdown() is: close() closes the socket id for the process but the connection is still opened if another process shares this socket id. The connection stays opened both for read and write, and sometimes this is very important. shutdown() breaks the connection for all processes sharing the socket id. Those who try to read will detect EOF, and those who try to write will reseive SIGPIPE, possibly delayed while the kernel socket buffer will be filled. Additionally, shutdown() has a second argument which denotes how to close the connection: 0 means to disable further reading, 1 to disable writing and 2 disables both.

52.

How Do I Properly Close A Socket?

Answer»

This question is usually asked by people who try close(), because they have seen that that is what they are supposed to do, and then run NETSTAT and see that their socket is STILL active. YES, close() is the CORRECT method. To read about the TIME_WAIT state, and why it is important, refer to ``2.7 Please explain the TIME_WAIT state.''.

This question is usually asked by people who try close(), because they have seen that that is what they are supposed to do, and then run netstat and see that their socket is still active. Yes, close() is the correct method. To read about the TIME_WAIT state, and why it is important, refer to ``2.7 Please explain the TIME_WAIT state.''.

53.

How Do I Get The Port Number For A Given Service?

Answer»

Use the getservbyname() routine. This will return a pointer to a servent structure. You are interested in the s_port field, which contains the PORT number, with correct byte ordering (so you don't NEED to call htons() on it). Here is a sample routine.

/* Take a service name, and a service type, and return a port number. If the service name is not found, it tries it as a decimal number. The number returned is byte ordered for the network. */

int atoport(char *service, char *proto)

{

int port;

long int lport;

STRUCT servent *serv;

char *errpos;

/* First try to READ it from /etc/services */

serv = getservbyname(service, proto);

if (serv != NULL)

port = serv->s_port;

else { 

/* Not in services, maybe a number? */

lport = strtol(service,&errpos,0);

if ( (errpos[0] != 0) || (lport < 1) 

|| (lport > 5000) )

return -1; 

/* Invalid port address */

port = htons(lport);

}

return port;

}

Use the getservbyname() routine. This will return a pointer to a servent structure. You are interested in the s_port field, which contains the port number, with correct byte ordering (so you don't need to call htons() on it). Here is a sample routine.

/* Take a service name, and a service type, and return a port number. If the service name is not found, it tries it as a decimal number. The number returned is byte ordered for the network. */

int atoport(char *service, char *proto)

{

int port;

long int lport;

struct servent *serv;

char *errpos;

/* First try to read it from /etc/services */

serv = getservbyname(service, proto);

if (serv != NULL)

port = serv->s_port;

else { 

/* Not in services, maybe a number? */

lport = strtol(service,&errpos,0);

if ( (errpos[0] != 0) || (lport < 1) 

|| (lport > 5000) )

return -1; 

/* Invalid port address */

port = htons(lport);

}

return port;

}

54.

How Can I Tell When A Socket Is Closed On The Other End?

Answer»

If the peer calls close() or exits, without having messed with SO_LINGER, then our calls to read() should return 0. It is LESS CLEAR what happens to write() calls in this case; I would expect EPIPE, not on the next call, but the one after.

If the peer reboots, or sets l_onoff = 1,l_linger = 0 and then closes, then we should get ECONNRESET (eventually) from read(), or EPIPE from write().

When write() returns EPIPE, it also raises the SIGPIPE signal - you NEVER see the EPIPE error unless you handle or ignore the signal.

If the peer remains unreachable, we should get some other error.

Don't think that write() can LEGITIMATELY return 0. read() should return 0 on receipt of a FIN from the peer, and on all following calls.

So yes, you must expect read() to return 0.

As an example, suppose you are receiving a file down a TCP link; you might handle the return from read() like this:

rc = read(SOCK,buf,sizeof(buf));

if (rc > 0)

{

write(file,buf,rc);

/* error checking on file omitted */

}

else if (rc == 0)

{

close(file);

close(sock);

/* file received successfully */

}

else /* rc < 0 */

{

/* close file and delete it, since data 

is not complete report error, or whatever */

}

If the peer calls close() or exits, without having messed with SO_LINGER, then our calls to read() should return 0. It is less clear what happens to write() calls in this case; I would expect EPIPE, not on the next call, but the one after.

If the peer reboots, or sets l_onoff = 1,l_linger = 0 and then closes, then we should get ECONNRESET (eventually) from read(), or EPIPE from write().

When write() returns EPIPE, it also raises the SIGPIPE signal - you never see the EPIPE error unless you handle or ignore the signal.

If the peer remains unreachable, we should get some other error.

Don't think that write() can legitimately return 0. read() should return 0 on receipt of a FIN from the peer, and on all following calls.

So yes, you must expect read() to return 0.

As an example, suppose you are receiving a file down a TCP link; you might handle the return from read() like this:

rc = read(sock,buf,sizeof(buf));

if (rc > 0)

{

write(file,buf,rc);

/* error checking on file omitted */

}

else if (rc == 0)

{

close(file);

close(sock);

/* file received successfully */

}

else /* rc < 0 */

{

/* close file and delete it, since data 

is not complete report error, or whatever */

}

55.

What Are Sockets?

Answer»

Sockets are just like "worm holes" in science fiction. When things go into one end, they (should) COME out of the other. Different kinds of sockets have different properties. Sockets are either connection- oriented or connectionless. Connection-oriented sockets allow for data to FLOW BACK and forth as NEEDED, while connectionless sockets (also known as datagram sockets) allow only one message at a time to be transmitted, without an open connection. There are also different SOCKET families. The two most common are AF_INET for internet connections, and AF_UNIX for unix IPC (interprocess communication). As stated earlier, this FAQ deals only with AF_INET sockets.

Sockets are just like "worm holes" in science fiction. When things go into one end, they (should) come out of the other. Different kinds of sockets have different properties. Sockets are either connection- oriented or connectionless. Connection-oriented sockets allow for data to flow back and forth as needed, while connectionless sockets (also known as datagram sockets) allow only one message at a time to be transmitted, without an open connection. There are also different socket families. The two most common are AF_INET for internet connections, and AF_UNIX for unix IPC (interprocess communication). As stated earlier, this FAQ deals only with AF_INET sockets.

56.

What Do We Expect?

Answer»

The child detects an EOF from its stdin, it closes the socket (assuming CONNECTION break) and exits. The server in its turn detects EOF, closes connection and exits. The parent detects EOF, makes the wait() system call and exits. What do we see instead? The socket instance in the parent process is still opened for writing and reading, though the parent never writes. The server never detects EOF and waits for more data from the client forever. The parent never sees the connection is CLOSED and hangs forever and the server hangs too. Unexpected deadlock!

You should change the client fragment as follows:

if( fork() ) { 

/* The child */

while( gets(BUFFER) }

write(s,buffer,strlen(buffer));

shutdown(s,1);

/* Break the connection

for writing, The server will detect EOF now.

Note: reading from the socket is still allowed.

The server may SEND some more data

after receiving EOF, why not? */

exit(0);

}

The child detects an EOF from its stdin, it closes the socket (assuming connection break) and exits. The server in its turn detects EOF, closes connection and exits. The parent detects EOF, makes the wait() system call and exits. What do we see instead? The socket instance in the parent process is still opened for writing and reading, though the parent never writes. The server never detects EOF and waits for more data from the client forever. The parent never sees the connection is closed and hangs forever and the server hangs too. Unexpected deadlock!

You should change the client fragment as follows:

if( fork() ) { 

/* The child */

while( gets(buffer) }

write(s,buffer,strlen(buffer));

shutdown(s,1);

/* Break the connection

for writing, The server will detect EOF now.

Note: reading from the socket is still allowed.

The server may send some more data

after receiving EOF, why not? */

exit(0);

}

57.

When Should I Use Shutdown()?

Answer»

shutdown() is useful for delineating when you are done providing a request to a server using TCP. A typical use is to SEND a request to a server followed by a shutdown(). The server will read your request followed by an EOF (read of 0 on most unix implementations). This tells the server that it has your full request. You then go read blocked on the socket. The server will process your request and send the necessary data back to you followed by a close. When you have finished READING all of the response to your request you will read an EOF thus signifying that you have the WHOLE response. It should be noted the TTCP (TCP for Transactions -- see R. Steven's home PAGE) provides for a better method of tcp transaction management.

shutdown() is useful for delineating when you are done providing a request to a server using TCP. A typical use is to send a request to a server followed by a shutdown(). The server will read your request followed by an EOF (read of 0 on most unix implementations). This tells the server that it has your full request. You then go read blocked on the socket. The server will process your request and send the necessary data back to you followed by a close. When you have finished reading all of the response to your request you will read an EOF thus signifying that you have the whole response. It should be noted the TTCP (TCP for Transactions -- see R. Steven's home page) provides for a better method of tcp transaction management.

58.

If Bind() Fails, What Should I Do With The Socket Descriptor?

Answer»

If you are EXITING, I have been ASSURED by ANDREW that all unixes will close open file descriptors on exit. If you are not exiting THOUGH, you can just close it with a REGULAR close() call.

If you are exiting, I have been assured by Andrew that all unixes will close open file descriptors on exit. If you are not exiting though, you can just close it with a regular close() call.

59.

What Is With The Second Parameter In Bind()?

Answer»

The man page shows it as "struct sockaddr *my_addr". The sockaddr struct though is just a place holder for the structure it REALLY wants. You have to pass different structures DEPENDING on what kind of socket you have. For an AF_INET socket, you need the sockaddr_in structure.

It has three FIELDS of interest:

1.sin_family

Set this to AF_INET.

2.sin_port

The network byte-ordered 16 BIT port number

3.sin_addr

The host's ip number.

This is a struct in_addr,

which contains only one field, 

s_addr which is a u_long.

The man page shows it as "struct sockaddr *my_addr". The sockaddr struct though is just a place holder for the structure it really wants. You have to pass different structures depending on what kind of socket you have. For an AF_INET socket, you need the sockaddr_in structure.

It has three fields of interest:

1.sin_family

Set this to AF_INET.

2.sin_port

The network byte-ordered 16 bit port number

3.sin_addr

The host's ip number.

This is a struct in_addr,

which contains only one field, 

s_addr which is a u_long.

60.

How Do Sockets Work?

Answer»

The implementation is left up to the vendor of your particular unix, but from the point of view of the programmer, connection-oriented sockets work a lot like files, or PIPES. The most NOTICEABLE difference, once you have your file descriptor is that read() or write() calls may actually read or write FEWER bytes than requested. If this happens, then you will have to MAKE a second call for the rest of the data. There are examples of this in the source code that ACCOMPANIES the faq.

The implementation is left up to the vendor of your particular unix, but from the point of view of the programmer, connection-oriented sockets work a lot like files, or pipes. The most noticeable difference, once you have your file descriptor is that read() or write() calls may actually read or write fewer bytes than requested. If this happens, then you will have to make a second call for the rest of the data. There are examples of this in the source code that accompanies the faq.