/* $Id: chat4.c,v 1.5 2007/10/11 23:51:03 tacha Exp $ */ /* * Copyright (c) 2007, 2008 * Tatoku Ogaito. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Tatoku Ogaito. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "common.h" #define BUF_LEN (512) #define NAME_LEN (128) struct sockaddr_in dst; int setup_client(char *, char *); int do_chat(int); int main(int argc, char *argv[]) { int ch; int s; char *hostname = "localhost"; /* default remote host */ char *service = SERVERPORT; /* default remote port (defined in common.h)*/ /* parse option character from command line argments */ while ((ch = getopt(argc, argv, "h:p:")) != -1) { switch (ch) { case 'h': hostname = strdup(optarg); break; case 'p': service = strdup(optarg); break; case '?': default: exit(1); } } argc -= optind; argv += optind; if ((s = setup_client(hostname, service)) < 0) exit(1); do_chat(s); return 0; } int setup_client(char *hostname, char *service) { int sock; struct hostent *host_info; struct servent *service_info; if ((host_info = gethostbyname(hostname)) == NULL) { perror("gethostbyname"); return -1; } memset((char *)&dst, 0, sizeof(dst)); dst.sin_family = AF_INET; /* setup destination address */ memcpy((char *)&dst.sin_addr, host_info->h_addr, host_info->h_length); if (isdigit((int)*service)) { dst.sin_port = htons(atoi(service)); /* need to convert to network order */ } else { if ((service_info = getservbyname(service, "tcp")) == NULL) { perror("getservbyname"); return -1; } /* setup destination port */ dst.sin_port = service_info->s_port; /* already network order */ } if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return -1; } if (connect(sock, (struct sockaddr *)&dst, sizeof(dst)) == -1) { perror("connect"); return -1; } return sock; } int do_chat(int s) { char send_buffer[BUF_LEN]; char recv_buffer[BUF_LEN]; char username[NAME_LEN], buf1[BUF_LEN]; struct sockaddr_in ss; socklen_t socksize = sizeof(ss); fd_set read_set, read_ready; int ret; size_t count; int sendto_flags = 0; FD_ZERO(&read_set); FD_SET(STDIN_FILENO, &read_set); /* stdin */ FD_SET(s, &read_set); /* socket */ printf("Input your name => "); scanf("%s", username); /* Caution: buffer overflow may happen. */ /* main loop */ while (1) { read_ready = read_set; /* wait until some of FD become ready */ ret = select(s+1, &read_ready, NULL, NULL, NULL); switch(ret) { case -1: fprintf(stderr, "select:err\n"); exit(1); case 0: /* timeout (should not happen in our case) */ break; default: if (FD_ISSET(s, &read_ready)) { /* data from remote node */ socksize = sizeof(ss); memset(&ss, 0, socksize); memset(recv_buffer, 0, sizeof(recv_buffer)); if ((count = read(s, recv_buffer, sizeof(recv_buffer))) < 0) { perror("read"); } else if (count == 0) { ; } else { printf("%s", recv_buffer); } } if (FD_ISSET(STDIN_FILENO, &read_ready)) { /* data from keyboard */ if (NULL == fgets(buf1, sizeof(buf1), stdin) || strncmp(buf1, "quitquit", 8) == 0) return 0; snprintf(send_buffer, sizeof(send_buffer), "[%s] %s", username, buf1); if (sendto(s, send_buffer, strlen(send_buffer), sendto_flags, NULL, 0) < 0) { perror("sendto"); exit(1); } } } } }