next up previous contents
Next: Usage Up: A talk program Previous: Design of the interface

Implementation

Our code for s_send_msg() is just a little more than a few printfs.

void   s_send_msg(u_long sno, char *host, char *sender, char *msg)
{
    printf("\n...............%s@%d@%s................\n%s",
           sender, sno, host, msg);
    printf("....................over..................\n");
    talk2_unbind(0);
    talk2_bind(host, sno, 0, 0);
}
Besides writing the message from the client onto the terminal, we also establish an RPC connection to the sender.

To receive messages from a peer, the Talk2 program needs to be an RPC server, to send messages it must read stdin and acts as an RPC client. This requires the Talk2 program to do I/O multiplexing, in our case, the Talk2 program must handle the input from both the network communication channel for RPCes and the terminal input. powerRPC accommodates this easily by providing a set of server library functions to set up I/O handlers for a particular file descriptor. Although we could use the INIT_AFTER_REGISTER property to insert all of the code, we take this chance to write the server main() function ourselves using the powerRPC generated code and libraries.

Thus we have the following code,

void    handle_stdin(int fd)
{
    char            msg[1024];
    int             cnt;
    cnt = read(fd, msg, 1023);
    if (cnt <= 0)
        exit(1);

    msg[cnt] = '\0';
    send_msg(myprog, myhost, myname, msg);
}


int     main(int argc, char **argv)
{
    fd_set          fds;
    SVCXPRT        *mytxp;
    int             serv_sock;
    int             dtsz;
    char            msg[4096];

    if (argc < 2) {
        printf("Usage: %s -n talker -p program# [-c peer -P perr_prog#]\n",
               argv[0]);
        exit(0);
    }
    getoption(argc, argv);

    gethostname(myhost, 1023);

    if (strlen(peer_host)) {
        if (!talk2_bind(peer_host, peer_no, 0, 0)) {
            printf("Can not find peer to talk.\n");
            exit(1);
        }
    }
    pw_serv_init();

    if (!talk2_1_reg(RPC_ANYSOCK, myprog, 1, IPPROTO_UDP))
        exit(1);

    myprog = myprog == 0 ? TALK : myprog;

    printf("My program number is %d\n", myprog);
    signal(SIGINT, unset_myprog);

    pw_serv_input_handler(0, handle_stdin);

    pw_serv_mainloop(0, 0, 0, 0);
}

As you can the see, the handle_stdin() function simply reads something from stdin and call the send_msg() RPC to deliver it to a connected peergif.

The main server function is more interesting. First, it reads some options. To allow two talk2 program to sit on the same machine, we let them to use whatever program number the user gives (if none is given at the command line option then the one defined in the IDL will be used). The first instance of Talk2 has no one to talk with, however, a subsequent Talk2 can talk to it by supplying the peer hostname and program number, through the ``-c" and ``-P" options respectively. So when the peer_host variable is set, we try to make connection to another Talk2. Then we initialize the server code by calling pw_serv_init() function. Then we register our server by calling the generated talk2_1_reg() function, with the program number defined in myprog variable. We then set up the input handler for stdin. Finally, Talk2 enters its mainloop by calling pw_serv_mainloop() with default arguments.


next up previous contents
Next: Usage Up: A talk program Previous: Design of the interface

Copyright (C) Netbula LLC, 1996