exemplo_eco
Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
— | exemplo_eco [2023/09/12 16:14] (atual) – criada - edição externa 127.0.0.1 | ||
---|---|---|---|
Linha 1: | Linha 1: | ||
+ | ====== Servidor de ECO ====== | ||
+ | Um servidor de ECO simplesmente recebe uma mensagem e retorna a mesma mensagem (eco) sem modificações. | ||
+ | |||
+ | ===== Cliente TCP de ECO ===== | ||
+ | Este cliente recebe uma mensagem via linha de comando e envia 10 vezes (1 por segundo) para o servidor de eco. | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main(int argc, char ** argv ) | ||
+ | { | ||
+ | int iSock; | ||
+ | int iBytes; | ||
+ | |||
+ | | ||
+ | char buffer1[100]; | ||
+ | char buffer[100]; | ||
+ | int iContador; | ||
+ | |||
+ | iSock = socket(AF_INET, | ||
+ | |||
+ | if( iSock == -1) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | if( connect(iSock, | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | for( iContador = 0; iContador < 10; iContador ++) | ||
+ | { | ||
+ | sprintf(buffer1, | ||
+ | printf(" | ||
+ | |||
+ | if ((iBytes=send(iSock, | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | memset(buffer, | ||
+ | |||
+ | if ((iBytes=recv(iSock, | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | buffer[iBytes] = ' | ||
+ | printf(" | ||
+ | sleep(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Servidor TCP tratando múltiplos clientes com a função select ===== | ||
+ | |||
+ | Este exemplo utiliza a função [[select]] para receber e responder para um determinado cliente. | ||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #define MAXLINE 4096 | ||
+ | |||
+ | |||
+ | int MySocket(int iFamily, int iType, int iProtocol) | ||
+ | { | ||
+ | int iBytes; | ||
+ | |||
+ | if ( (iBytes = socket(iFamily, | ||
+ | { | ||
+ | perror(" | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | void MyBind(int iFd, const struct sockaddr *sa, socklen_t iLen) | ||
+ | { | ||
+ | if (bind(iFd, sa, iLen) < 0) | ||
+ | { | ||
+ | perror(" | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | void MyListen(int iFd, int backlog) | ||
+ | { | ||
+ | if (listen(iFd, | ||
+ | { | ||
+ | perror(" | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | int MySelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) | ||
+ | { | ||
+ | int iBytes; | ||
+ | |||
+ | if ( (iBytes = select(nfds, | ||
+ | { | ||
+ | perror(" | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | int MyAccept(int iFd, struct sockaddr *sa, socklen_t *salenptr) | ||
+ | { | ||
+ | int iSocket; | ||
+ | |||
+ | if ( (iSocket = accept(iFd, sa, salenptr)) < 0) | ||
+ | { | ||
+ | perror(" | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | void MyClose(int iFd) | ||
+ | { | ||
+ | if (close(iFd) == -1) | ||
+ | { | ||
+ | perror(" | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | int main(int argc, char **argv) | ||
+ | { | ||
+ | int i, maxi, maxfd, listenfd, connfd, sockfd; | ||
+ | int nready, client[FD_SETSIZE]; | ||
+ | ssize_t n; | ||
+ | fd_set rset, allset; | ||
+ | char buf[MAXLINE]; | ||
+ | socklen_t clilen; | ||
+ | struct sockaddr_in cliaddr, servaddr; | ||
+ | |||
+ | listenfd = MySocket(AF_INET, | ||
+ | |||
+ | bzero(& | ||
+ | servaddr.sin_family | ||
+ | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); | ||
+ | servaddr.sin_port | ||
+ | |||
+ | MyBind(listenfd, | ||
+ | |||
+ | MyListen(listenfd, | ||
+ | |||
+ | maxfd = listenfd; /* 1 conexao */ | ||
+ | maxi = -1; /* indice do vetor que vai conter todos os sockets abertos */ | ||
+ | for (i = 0; i < FD_SETSIZE; i++) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | FD_ZERO(& | ||
+ | FD_SET(listenfd, | ||
+ | |||
+ | while(1) | ||
+ | { | ||
+ | rset = allset; /* zerando a estrutura */ | ||
+ | | ||
+ | |||
+ | if (FD_ISSET(listenfd, | ||
+ | { | ||
+ | clilen = sizeof(cliaddr); | ||
+ | connfd = MyAccept(listenfd, | ||
+ | printf(" | ||
+ | |||
+ | for (i = 0; i < FD_SETSIZE; i++) | ||
+ | { | ||
+ | if (client[i] < 0) | ||
+ | { | ||
+ | client[i] = connfd; /* salva o descritor no vetor */ | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | if (i == FD_SETSIZE) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | FD_SET(connfd, | ||
+ | if (connfd > maxfd) | ||
+ | { | ||
+ | maxfd = connfd; /* maior descritor possivel, utilizado no select */ | ||
+ | } | ||
+ | if (i > maxi) | ||
+ | { | ||
+ | maxi = i; /* maximo de clientes */ | ||
+ | } | ||
+ | |||
+ | if (--nready <= 0) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | for (i = 0; i <= maxi; i++) /* verifica se os clientes tem dados */ | ||
+ | { | ||
+ | if ( (sockfd = client[i]) < 0) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | if (FD_ISSET(sockfd, | ||
+ | { | ||
+ | if ( (n = recv(sockfd, | ||
+ | { | ||
+ | MyClose(sockfd); | ||
+ | FD_CLR(sockfd, | ||
+ | client[i] = -1; | ||
+ | | ||
+ | else | ||
+ | { | ||
+ | printf(" | ||
+ | send(sockfd, | ||
+ | } | ||
+ | |||
+ | if (--nready <= 0) | ||
+ | { | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Servidor TCP tratando múltiplos clientes com fork/wait ===== | ||
+ | |||
+ | Este servidor utiliza as funções [[fork]] e [[wait]] para tratamento de vários clientes. Neste exemplo, caso vários clientes terminem simultâneamente, | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #define MAXLINE 4096 | ||
+ | |||
+ | /* função que irá verificar o status dos processos filhos */ | ||
+ | void signal_handler_function(int iSignal) | ||
+ | { | ||
+ | pid_t iPid; | ||
+ | int iStatus; | ||
+ | | ||
+ | iPid = wait(& | ||
+ | |||
+ | | ||
+ | if( WIFEXITED(iStatus) ) | ||
+ | { | ||
+ | fprintf(stderr, | ||
+ | } | ||
+ | else if(WIFSIGNALED(iStatus)) | ||
+ | { | ||
+ | fprintf(stderr, | ||
+ | } | ||
+ | else if(WIFSTOPPED(iStatus)) | ||
+ | { | ||
+ | fprintf(stderr, | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | pid_t iFilho; | ||
+ | int iSock; | ||
+ | | ||
+ | |||
+ | /* registrando sinal da função para tratar do filho */ | ||
+ | if( signal(SIGCHLD , signal_handler_function) == SIG_ERR ) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | iSock = socket(AF_INET, | ||
+ | if( iSock == -1) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | if( bind(iSock, (struct sockaddr *)& | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | if( listen( iSock, 10 ) < 0) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | { | ||
+ | int iFd; | ||
+ | struct sockaddr_in client_addr; | ||
+ | socklen_t sin_size; | ||
+ | char szMensagem[100]; | ||
+ | |||
+ | sin_size = sizeof(struct sockaddr_in); | ||
+ | |||
+ | if( (iFd = accept(iSock, | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | printf(" | ||
+ | iFilho = fork(); | ||
+ | printf(" | ||
+ | if( iFilho < 0) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | if( iFilho == 0) /* processo filho */ | ||
+ | { | ||
+ | char buf[MAXLINE]; | ||
+ | | ||
+ | | ||
+ | { | ||
+ | send(iFd, buf, nBytes, 0); | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | close(iFd); /* fecha a conexão no pai, o filho fica aberto */ | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Servidor TCP tratando múltiplos clientes com fork/ | ||
+ | Este servidor utiliza as funções [[fork]] e [[waitpid]] para tratamento de vários clientes. Neste exemplo, caso vários clientes terminem simultâneamente, | ||
+ | |||
+ | <code c> | ||
+ | /* servidor_eco_forktcp_waitpid.c */ | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #define MAXLINE 4096 | ||
+ | |||
+ | /* função que irá verificar o status dos processos filhos */ | ||
+ | void signal_handler_function(int iSignal) | ||
+ | { | ||
+ | pid_t iPid; | ||
+ | int iStatus; | ||
+ | | ||
+ | /* espera qualquer filho terminar sem bloquear o processo. Com wait | ||
+ | ocorre a possibilidade de perder-se sinais de alguns filhos, gerando | ||
+ | processos defunct. */ | ||
+ | | ||
+ | { | ||
+ | fprintf(stderr, | ||
+ | if( WIFEXITED(iStatus) ) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | else if(WIFSIGNALED(iStatus)) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | else if(WIFSTOPPED(iStatus)) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | pid_t iFilho; | ||
+ | int iSock; | ||
+ | | ||
+ | |||
+ | /* registrando sinal da função para tratar do filho */ | ||
+ | if( signal(SIGCHLD , signal_handler_function) == SIG_ERR ) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | iSock = socket(AF_INET, | ||
+ | if( iSock == -1) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | if( bind(iSock, (struct sockaddr *)& | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | if( listen( iSock, 10 ) < 0) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | { | ||
+ | int iFd; | ||
+ | struct sockaddr_in client_addr; | ||
+ | socklen_t sin_size; | ||
+ | char szMensagem[100]; | ||
+ | |||
+ | sin_size = sizeof(struct sockaddr_in); | ||
+ | |||
+ | if( (iFd = accept(iSock, | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | printf(" | ||
+ | iFilho = fork(); | ||
+ | if( iFilho < 0) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | if( iFilho != 0 ) | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | |||
+ | if( iFilho == 0) /* processo filho */ | ||
+ | { | ||
+ | char buf[MAXLINE]; | ||
+ | | ||
+ | | ||
+ | { | ||
+ | send(iFd, buf, nBytes, 0); | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | close(iFd); /* fecha a conexão no pai, o filho fica aberto */ | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Servidor de ECO tratando múltiplos clientes com threads POSIX ===== | ||
+ | |||
+ | Este exemplo trabalha com as [[threads_posix|threads POSIX]] do Linux. | ||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #include < | ||
+ | |||
+ | #define MAXLINE 4096 | ||
+ | |||
+ | static int siFd; | ||
+ | |||
+ | void * trata_conexao(void * pArg ) | ||
+ | { | ||
+ | int iFd = siFd; | ||
+ | char buf[MAXLINE]; | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | { | ||
+ | send(iFd, buf, nBytes, 0); | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | } | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | |||
+ | iSock = socket(AF_INET, | ||
+ | if( iSock == -1) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | if( bind(iSock, (struct sockaddr *)& | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | if( listen( iSock, 10 ) < 0) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | { | ||
+ | struct sockaddr_in client_addr; | ||
+ | socklen_t sin_size; | ||
+ | pthread_t tId; | ||
+ | |||
+ | sin_size = sizeof(struct sockaddr_in); | ||
+ | |||
+ | if( (siFd = accept(iSock, | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | printf(" | ||
+ | pthread_create(& | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Este outro exemplo é só para ilustrar que o programa pode fazer outras coisas, para isto tem-se uma thread que recebe as conexões e chama outras threads para tratamento individual da conexão. | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #include < | ||
+ | |||
+ | #define MAXLINE 4096 | ||
+ | |||
+ | void * trata_conexao(void * pArg) | ||
+ | { | ||
+ | int iFd = *((int *)pArg); /* cópia do ponteiro */ | ||
+ | char buf[MAXLINE]; | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | { | ||
+ | send(iFd, buf, nBytes, 0); | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | } | ||
+ | |||
+ | void * aceita_conexao(void * pArg) | ||
+ | { | ||
+ | int iFd, iSock; | ||
+ | | ||
+ | |||
+ | iSock = socket(AF_INET, | ||
+ | if( iSock == -1) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | if( bind(iSock, (struct sockaddr *)& | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | if( listen( iSock, 10 ) < 0) | ||
+ | { | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | | ||
+ | { | ||
+ | struct sockaddr_in client_addr; | ||
+ | socklen_t sin_size; | ||
+ | pthread_t tId; | ||
+ | |||
+ | sin_size = sizeof(struct sockaddr_in); | ||
+ | |||
+ | if( (iFd = accept(iSock, | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | fprintf(stderr," | ||
+ | |||
+ | if( pthread_create(& | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | | ||
+ | } | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | { | ||
+ | fprintf(stderr, | ||
+ | sleep(5); | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | --- // |
exemplo_eco.txt · Última modificação: 2023/09/12 16:14 por 127.0.0.1