/* * Program: Simple chat client multiplexing IO * * Author: Pedro Velho * * Date: 15/08/2005 * * This simple cliente makes a loop where it * can concurrently detetect keyboard typing input and * receive messages from the socket. This make possible * the construction of a simple chat environment where * what a client types appears in the terminal of * each other client already connected. * */ #include //gethostbyname #include //printf #include //struct sockaddr_in, AFINET, SOCK_STREAM #include //socket, bind, accept #include //struct time_val #include #include // hton #include // signal #include #include //fileio cpp class. getline using namespace std; #define BUFFER_MAX_SIZE 1200 #define STDIN 0 int main(int argc, char **argv){ int sockfd; struct sockaddr_in server_addr; struct hostent *he; string buf; string name=""; //cria o socket e armazena o descritor em sockfd sockfd = socket(AF_INET, SOCK_STREAM, 0); //efetua concistencia da chamada de sistema socket if(sockfd == -1){ perror("socket"); exit(1); } //tres parametros sao necessarios para a aplicacao funcionar if (argc != 4) { printf("Erro uso correto: \n"); printf("\n %s \n\n", argv[0]); exit(1); } name = name+argv[3]; //encontra o endereco IP usando o servidor de DNS, essa aplicacao //aceita tanto o nome como a notacao de pontos e numeros exemplo: // localhost // 127.0.0.1 if ((he=gethostbyname(argv[1])) == NULL) { // get the host info perror("gethostbyname"); exit(1); } //especifica a familia do endereco internet server_addr.sin_family = AF_INET; // host byte order //especifica o numero da porta que vai conectar server_addr.sin_port = htons(atoi(argv[2])); // short, network byte order //especifica o endereco de rede do servidor server_addr.sin_addr = *((struct in_addr *)he->h_addr); //zera o resto da struct sockaddr_in memset(&(server_addr.sin_zero), '\0', 8); // zero the rest of the struct //conect com o servidor no endereco especificado acima if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { perror("connect"); exit(1); } char temp[BUFFER_MAX_SIZE]; fd_set temp_set; int size; while(true){ //zera o conjunto de descritor aos quais esta observando FD_ZERO(&temp_set); //acrescenta o socket no conjunto de descritores observados FD_SET(sockfd, &temp_set); //acrescenta a entrada padrão stdin=0 no conjunto de descritores que esta observando FD_SET(STDIN , &temp_set); printf("type a message> "); fflush(NULL); //a chamada select bloqueia ate que uma mudanca o ocorra em um dos //descritores de arquivo existentes, neste caso tempo apenas um //conjunto de descritores dos quais monitoraremos mundacas //com relacao a dados prontos para a leitura. if( select(sockfd+1, &temp_set, NULL, NULL, NULL) == -1) { //se acontece um erro na chamada select entra aqui perror("select()"); close(sockfd); exit(1); }else{ //caso nao aconteca um erro na chamada select verifica quais //descritores foram modificados //se for um signal de alteracao na socket entao //recebe uma mensagem mostrando-a na tela if(FD_ISSET(sockfd, &temp_set)){ buf=""; if((size = recv(sockfd, temp, BUFFER_MAX_SIZE, 0)) <= 0){ perror("recv"); break; } buf = buf+temp; printf("\n%s\n\n", buf.c_str()); fflush(NULL); } //se for um signal de alteracao no STDIN //le do teclado a string e a envia para o servidor if(FD_ISSET(STDIN, &temp_set)){ fflush(NULL); buf=""; getline(cin, buf); if( string("sair") == string(buf)) break; buf = name+" diz "+buf; if(send(sockfd, buf.c_str(), buf.size()+1, 0) == -1){ fprintf(stderr, "Erro durante o envio da mensagem!"); close(sockfd); exit(1); } } } } close(sockfd); }