• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

bertolo

mlan v3.0 o programa mais rasco com que alguma vez sonharam =P

8 mensagens neste tópico

Basicamente este programa server para comunicar via lan ou web ou mesmo dentro da própria maquina. bertolo 1-0 microsoft isto eles nunca fizeram LOOOOL ....claro está nao faz sentido eu sei.... isto foi um exercicio que fiz para usar threads, sockets e processos.

O servidor é lançado em primeiro lugar numa maquina. Depois o cliente e lançado e conecta.s ao servidor através do seu ip. Caso sejam ambos lançados na mesma maquina o ip e 127.0.0.1.

têm muito pouca utilidade. tenciono aperfeiçoa-lo. comentem.

Cliente

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>

#define PORT 1050
#define DIM 256

/*devolve string com horas no formato hh:mm:ss*/
char *horas(void)
{
time_t rawtime;
struct tm * timeinfo;
char *buffer;

buffer=(char *)malloc(sizeof(char)*20);
time ( &rawtime );
timeinfo = localtime ( &rawtime );
strftime (buffer,20,"%X",timeinfo);

return buffer;
}

int main(void)
{
char *tempo;
char nick[DIM];
char aux[DIM];
pid_t pid;
char buffer[DIM];
int sockfd,i;
struct sockaddr_in serv_addr;
struct hostent *server;
char addr[DIM];

/*tempo=(char *)malloc(sizeof(char)*20); nao e necessário */

/*prompt do ip e do nick*/
printf("IP: ");
scanf("%s",addr);
printf("NICK: ");
scanf("%s",nick);
while(getchar()!='\n');
strcat(nick,":");

/* cria socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
server = gethostbyname(addr);

/* solicita a ligação ao servidor */
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port = htons(PORT);
connect(sockfd,&serv_addr,sizeof(serv_addr));
printf("CONNECTED!\n");

/*filho-receptor*/
if ((pid = fork()) == 0) 
{
while(1)
  {
  /*recebe*/
  read(sockfd,buffer,DIM-1);
  printf("%s",buffer);
  for(i=0;i<DIM;i++)
   buffer[i]='\0';
  }
}

/*pai-emissor*/
else 
{
while(1)
{
/*envia*/
tempo=horas();
strcpy(aux,tempo);
free(tempo);
strcat(aux,"-");
  strcat(aux,nick);
fgets(buffer,DIM-1,stdin);
strcat(aux,buffer);
write(sockfd,aux,DIM);
for(i=0;i<DIM;i++)
  {
  aux[i]='\0';
  buffer[i]='\0';
  }
}
}
return 0;
}

Servidor

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>

#define PORT 1050
#define DIM 256

/*devolve string com horas no formato hh:mm:ss*/
char *horas(void)
{
time_t rawtime;
struct tm * timeinfo;
char *buffer;

buffer=(char *)malloc(sizeof(char)*20);
time ( &rawtime );
timeinfo = localtime ( &rawtime );
strftime (buffer,20,"%X",timeinfo);

return buffer;
}

char buffer[DIM];

void filho(int newsockfd) /*recebe*/
{
int i;
   while(1)
    {
    read(newsockfd,buffer,DIM); 
    printf("%s",buffer);
    for(i=0;i<DIM;i++)
      buffer[i]='\0';
    }
}

int main(void)
{
char *tempo;
char nick[DIM];
char aux[DIM];
int sockfd,clilen,newsockfd,i;
struct sockaddr_in serv_addr,cli_addr;
pthread_t threads[1];
printf("NICK: ");
scanf("%s",nick);
while(getchar()!='\n');
strcat(nick,":");
/*tempo=(char *)malloc(sizeof(char)*20);não e necessário*/
/* cria socket */
sockfd=socket(AF_INET,SOCK_STREAM,0);

/* socket associado ao porto*/
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(PORT);
bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr));
printf("SERVER READY!\n");

/* socket fica à espera da requisição de uma ligação */
listen(sockfd,5);

/* socket aceita ligação com o cliente */
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); 
printf("CONNECTED!\n");

/*filho-receptor*/
pthread_create(&threads[0], NULL,filho,newsockfd);
/*pai-emissor*/
while(1)
  {
  /*envia*/
  tempo=horas();
  strcpy(aux,tempo);
free(tempo);
  strcat(aux,"-");
  strcat(aux,nick);
  fgets(buffer,DIM-1,stdin);
  strcat(aux,buffer);
  write(newsockfd,aux,DIM);
  for(i=0;i<DIM;i++)
   {
   aux[i]='\0';
   buffer[i]='\0';
   }
  }

return 0;
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
tenciono aperfeiçoa-lo. comentem.

Só de olhar para o código (ainda não o copiei para a minha máquina):

Memory leak: tens 4 mallocs nos teu códigos e nenhum free().

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

qd o programa sai a memória é limpa

se alguem me ajudar a resolver os warnings agradecia pq nao tenho sido capaz

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Outras sugestões a nível de código texto:

a) Indenta o código.

:( Acaba com casts desnecessários (quase todos).

c) o espaço em branco é barato :D

a nível de código:

d) Revê o problema de memory leak

e) bzero() e bcopy() são funções "deprecadas". Substitui por memset() e memmove().

f) error checking em TUDO!!! read(), scanf(), malloc(), socket(), listen(), ...

a nível de funcionalidades:

g) o PORT, e o NICK podiam ser especificados no command line

h) ter a possibilidade de ter o prefixo das horas tanto no input como no output

Quanto aos warnings experimenta mudar a função filho (servidor) ...

void filho_velho(int newsockfd) { /* ... */ }
void *filho_novo(void *parametro) { /* ... */ }

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

a) tens razao nao sei pq nao o fiz

b)evitam muitos warnings

c)LOOL

d)solved

e)deprecada nao sei o que significa

f) eia tanto trabalho loooooooooool eventualmente senão fosse um exercicio tinha-o feito

g)opções...

h)tinha de usar ficheiro auxiliar

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
:( evitam muitos warnings

Eu não tenho warning nenhum nesta linha:

buffer = malloc(20);

excepto se compilar o código como C++, mas em C++ talvez fosse melhor usar new() e delete()[/i']

e) deprecada nao sei o que significa

"deprecada" é uma palavra que eu inveitei quando fiz o post (é um aportuguesamento da palavra inglesa "deprecated"). Quer dizer que, provavelmente, a função deixará de existir dentro dalgum tempo.

FUTURE DIRECTIONS

    This function may be withdrawn in a future version.

Embora o site que eu costumo usar para questões da biblioteca de C não refira que a função bcopy() está deprecada

( http://www.opengroup.org/onlinepubs/007908799/xsh/bcopy.html ).

h) tinha de usar ficheiro auxiliar

Porquê?

Não precisas de ficheiro auxiliar para imprimir a hora do input.

Podes imprimir a hora junto com os dados recebidos.

/* recebe */
/* ... incluindo o "cálculo" da hora actual ... */
printf("%s%s", hora_actual, buffer);

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

buffer = malloc(20);

isto pode dar bosta se compilares o codigo em maquinas muito diferentes da minha e da tua. por acaso 20 chega e sobra, mas esses casts sao indispensaveis para o bom funcionamento do programa. por vezes maquinas diferentes reservam tamanhos diferentes para os mesmos tipos de variaveis. isso que fizeste é muito susceptivel de dar seg fault.

quando escreves no teclado e carregas enter aparece imediatamente a string no ecrã. não cunheço nenhuma maneira para alterar essa string

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O cast a que eu me referia (o único cast na linha original) era

buffer = (char *)malloc(20);

O resto que estava na linha original não faz parte do cast

buffer = (char *)malloc(sizeof(char) * 20);

O cast está lá a mais. O cast é necessário em C++, porque C++ é mais esquisito (é menos tolerante) que o C -- mas em C++, acho eu, é melhor usar new() e delete(). Se, por alguma qualquer razão, te esqueceres do #include <stdlib.h>, o compilador não se queixa da linha com o cast. Mas essa linha devia originar uma queixa do compilador, para alertar o programador.

o sizeof(char) é, por definição, 1 (em qualquer compilador de C: no meu, no teu, num para o meu telemóvel, noutro para o microprocessador que abre os vidros do carro ou acende a luz do frigorífico, ...).

sizeof(char) * 20 = 1 * 20 = 20

Se queres mesmo ter uma indicação do tamanho no malloc, é melhor usar a variável que estás a alocar que o tipo dela

int *variavel;
variavel = malloc(sizeof *variavel * 20);

Se, daqui a 3 meses, eu precisar de mudar a variavel para double, só preciso de mudar 1 linha no código

double *variavel; /* era int *variavel */
variavel = malloc(sizeof *variavel * 20); /* sem alteração */

~~~~~~~~~~~~

Ah! Tens razão quanto à hora do input. Eu é que estava a ver mal.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora