FAQ

  • 1. How to use the uname command (or gethostname) to determine the name of my machine?

    struct utsname name;
    int ret;

    ret=uname(&name);
    if (ret<0) error("ERROR looking up machine information");
    printf("My machine name is %s",name.nodename);

    (Remember that space must be allocated for the results)

    You may find it easier to use the gethostname command to determine the name of your machine.

    #define NAME_LEN 100
    char name[NAME_LEN];
    int ret;

    ret=gethostname(name,NAME_LEN);
    if(ret < 0) error("Error in gethostname call");
    printf("My machine name is %s",name);

  • 2. In a JOIN_REQUEST message, what is the UDP port and TCP port that must be sent?
    The UDP port of the client where chat messages must be sent by the server - not the UDP port of the chat server!!
    The TCP port on which the info server (on the client) is listening for info requests - not the TCP port of the chat server!!

    For example, assume the server is running on the host bass.cmcl.cs.cmu.edu, UDP port 4000 and TCP port 4000. Assume the client is running on the host char.cmcl.cs.cmu.edu, listening for chat messages on UDP port 15000 and listening for information requests on TCP port 12000. Then, the JOIN_REQUEST must be as follows:

    JOIN_REQUEST memberName char.cmcl.cs.cmu.edu 15000 12000 \n

  • 3. How do I get the UDP (and TCP port) of the client? (or) Why would I want to use getsockname, and how do I use it?
    You have two options:
    (1) Ask for a particular port in the socket call. To this, you would use the bind call as follows: (Assume the desired port is a string called desiredPort)

    struct sockaddr_in myAddr;
    bzero((void *)&myAddr,sizeof(myAddr));
    myAddr.sin_family = AF_INET;
    myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    myAddr.sin_port = htons((unsigned short) atoi(desiredPort)) /* see next question for explanation */
    ret=bind(sockfd, (struct sockaddr *) &myAddr, sizeof(myAddr));
    if(ret < 0) errexit("Could not bind"); /* print error msg and exit */

    The problem with this approach is that the port you request may already be taken by someone else. In such a case, you have to manually try a different port number. An alternate approach is:.

    (2) Tell the kernel you don't care about the port number. thus, you would do:

    struct sockaddr_in myAddr;
    bzero((void *)&myAddr,sizeof(myAddr));
    myAddr.sin_family=AF_INET;
    myAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    myAddr.sin_port=0;
    ret=bind(sockfd,(struct sockaddr *) &myAddr, sizeof(myAddr));
    if(ret < 0) errexit("Could not bind");

    0 for the port number tells the kernel that it could assign any available port, rather than a particular one.
    In such a case, how do you tell which port the kernel has assigned? This is done using the getsockname call.

    Thus you'd do:
    int myAddrLen=sizeof(myAddr);
    ret=getsockname(sockfd,&myAddr,&myAddrLen);
    if(ret < 0) errexit("getsockname error");
    portKernelAssignedToMe=ntohs(myAddr.sin_port);

    portKernelAssignedToMe is an unsigned short, that contains the port number in host-order.
    Check the man pages of getsockname for more details

  • 4. What is this weird looking myAddr.sin_port = htons((unsigned short) atoi(desiredPort))?
    desiredPort is a string.
    atoi converts to an equivalent integer.
    port numbers are unsigned shorts, hence the cast.
    the port number must be given to bind in network order - hence the htons.

  • 5(a) I am forking off the UDP client as a seperate process which controls the chat window. In my design, the UDP client creates and binds a socket for receiving chat messages. It somehow needs to communicate with the parent process to convey the port number it has bound to (as the parent process is in charge of issuing the JOIN_REQUEST message, which includes the port number). How to do this?
    NOTE: There is a much simpler and more elegant solution to this problem. See 5(b).

    First note that you cannot use global variables for communicating between processes, as forking results in each process having a separate copy of each variable. In general, there are several mechanisms for Inter Process Communication (IPC) . These include pipes, named pipes (fifo), message queues etc. For this lab, you may use sockets for communicating between processes. There is no need for you to use pipes or other mechansims which we have not taught in class, but you may use them if you know how to.

    We recommend using sockets for communication. What this means is there is a *new UDP socket* just for communicating between parent and child. (You may also use TCP if you prefer it)
    Thus, parent code looks something like this:

    1. Create UDP socket for communicating with child.
    2. Determine its port number. Let it be internalUDPPortNum
    3. fork and exec udpClient with command line argument that includes internalUDPPortNum.
    4. wait for message from internalUDPPortNum.
    5. Read message and determine chatUDPPortNum.
    6. Send a TCP JOIN_REQUEST to the server that includes chatUDPPortNum.
    7. Wait for user input, TCP info requests etc.

    The child code looks something like this:

    1. Determine internalUDPPortNum from command line argument.
    2. Create UDP socket for listening to chat messages.
    3. Determine its port number. Let it be chatUDPPortNum.
    4. Send a message on internalUDPPortNum that basically conveys chatUDPPortNum.
    5. Wait for chat messages etc.

  • 5b. What's a simpler way of dealing with the above problem?
    It turns out that an exec'd program inherits any open file descriptors of the calling process by default (unless they are explicitly set to close on exec). This assumption can be exploited to avoid creation of a new socket between parent and child.

    Parent code looks something like this:
    1. Create UDP socket for listening to chat messages.
    2. Determine its port number. Let it be chatUDPPortNum.
    3. Determine the socket descriptor. Let it be chatUDPSocketDescriptor.
    4. fork and exec udpClient with command line argument that includes chatUDPSocketDescriptor.
    5. Close this socket created for listening to chat messages.
    6. Send a TCP JOIN_REQUEST to the server that includes chatUDPPortNum.
    7. Wait for user input, TCP info requests etc.

    Child code looks something like this:
    1. Determine socket descriptor for listening to chat messages from command line argument.
    2. Wait for chat messages on this descriptor.

  • 6. I am forking off the UDP client as a seperate process which controls the chat window. When the user types a !q to exit, how do I close the chat window ?
    Here's one possible way of dealing with the problem.
    kill(pid,sig) sends a signal with signal number sig to a process with id pid (man 2 kill for details). The parent process sends a signal to the UDP client process when it is about to exit. The UDP client traps the signal, closes the chat window and exits.

  • 7. How do I convert a unsigned short int into a string? How can the converse be done?
    Let portNum be an unsigned short int. To convert into a string str use sprintf(str,"%hu",portNum) . Remember that you must allocate enough buffer space for the string str .
    The converse (converting string str into unsigned short portNum can be done using portNum = (unsigned short) (atoi(str))

  • 8. How do I determine the length of a file?
    You can do this using the stat command. man stat for details.

    You can also do this by a combination of the two commands ftell and fseek . fseek takes you to a particular position in the file and ftell determines the current position in the file. Thus, if you fseek to the end of file and do an ftell , you can determine file length.

  • 9. How do I use FIFOs?
    Here is example code that uses a FIFO: fifo.c


    Sanjay Gopinatha Rao
    Last modified: Mon Nov 29 23:35:30 EST 1999