Jump to content
msmsms

programação com sockets em c

Recommended Posts

apocsantos

Boa noite,

Por acaso, mas só por acaso, deste uma vista de olhos nos links que te deixei anteriormente ? Mais concretamente no link para um .pdf onte encontras o que precisas para fazeres isto ?? Se aberto a esta hora certamente terias um o que pretendes a funcionar, com a excepção das threads. Mas cá fica o link novamente.

Quanto a threads, podes sempre usar a lib pthread, é relativamente acessivel de se trabalhar e a documentação é bastante aceitável.

P.S.: Penso que o que te "empatou" nesta tarefa foi teres escolhido uma abordagem "mais complexa". Eu teria feito diferente, como muitos outros teriam feito diferente. Eu teria posto o "grosso do trabalho" no servidor, e deixado o cliente o mais simples possivel.

Cordiais cumprimentos,

Apocsantos


"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Share this post


Link to post
Share on other sites
msmsms

Boa noite,

Por acaso, mas só por acaso, deste uma vista de olhos nos links que te deixei anteriormente ? Mais concretamente no link para um .pdf onte encontras o que precisas para fazeres isto ?? Se aberto a esta hora certamente terias um o que pretendes a funcionar, com a excepção das threads. Mas cá fica o link novamente.

Quanto a threads, podes sempre usar a lib pthread, é relativamente acessivel de se trabalhar e a documentação é bastante aceitável.

P.S.: Penso que o que te "empatou" nesta tarefa foi teres escolhido uma abordagem "mais complexa". Eu teria feito diferente, como muitos outros teriam feito diferente. Eu teria posto o "grosso do trabalho" no servidor, e deixado o cliente o mais simples possivel.

Cordiais cumprimentos,

Apocsantos

sim eu vi o teu site e foi lá que vi como fazer o passo 3 do problema:

3- colocar o cliente a terminar ligação atraves de mensagem quit

achei que queria passar esse sitio porque achavas util para ver como fazer a comunicação do cliente

mas vou explocar melhor esse site

eu estou de directa faz 48 horas eu nao sei como é que isto se aprende mas eu já venho a estudar isto faz muitas semanas, escolhendo a linguagem c para resolver

eu quando encontrei esse servidor pensei exactamente aquilo que dizes como ele cria tantos array para varios sockets e tem em conta ate tempos! acho que ate tem coisas que nao sao precisas para nada para ser gerada a difusao e avisos de entrada e saida de clientes

e entao pensei que seria fazer um cliente simples para esse servidor aparentemente bastate grande.

Edited by msmsms

Share this post


Link to post
Share on other sites
pikax

Queres fazer um tipo de ligacao muito complexa, esta' a faltar-me o nome desse tipo de rede. O mais simples de se fazer e' Cliente-Servidor, em que o servidor e' o unico que tem os enderecos e portas dos clientes, basicamente o cliente ligasse e o servidor manda uma mensagem que o utilizador 'X' entrou, quando algum utilizado manda uma mensagem, o servidor reenvia para os demais clientes.

E' normal que os exemplos que vejas seja so' entre 1 cliente para 1 servidor, pelo que percebi estas a utilizar TCP/IP, basicamente o que tens que fazer e' ter um socket 'a escuta de novas conneccoes, quando um novo utlizador se liga ao servidor, vais guardar esse socket num container(uma lista, map, vector, array, set,etc), depois basta percurreres esse container quando queres mandar as mensagens para todos os clientes.

Obs: Nao queiras dar um passo maior que as pernas quando tens prazos para cumprir.


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
msmsms

Queres fazer um tipo de ligacao muito complexa, esta' a faltar-me o nome desse tipo de rede. O mais simples de se fazer e' Cliente-Servidor, em que o servidor e' o unico que tem os enderecos e portas dos clientes, basicamente o cliente ligasse e o servidor manda uma mensagem que o utilizador 'X' entrou, quando algum utilizado manda uma mensagem, o servidor reenvia para os demais clientes.

E' normal que os exemplos que vejas seja so' entre 1 cliente para 1 servidor, pelo que percebi estas a utilizar TCP/IP, basicamente o que tens que fazer e' ter um socket 'a escuta de novas conneccoes, quando um novo utlizador se liga ao servidor, vais guardar esse socket num container(uma lista, map, vector, array, set,etc), depois basta percurreres esse container quando queres mandar as mensagens para todos os clientes.

Obs: Nao queiras dar um passo maior que as pernas quando tens prazos para cumprir.

eu ja tenho o servidor a terminar se ele da para fazer de forma mais simples (menos codigos ou funcoes) eu nao sei

so preciso do cliente (tem de haver mais de um socket em cliente tanbem?

Share this post


Link to post
Share on other sites
pikax
eu ja tenho o servidor a terminar se ele da para fazer de forma mais simples (menos codigos ou funcoes) eu nao sei

so preciso do cliente (tem de haver mais de um socket em cliente tanbem?

O programa de servidor que tens e' "sacado" da net, aposto que deves ter olhado para aquilo algumas vezes para tentar perceber, mas nao percebeste nada(ou quase nada) do que o codigo faz, entao tentaste implementar um cliente, mas como nao percebes muito bem o conceito de sockets, nao conseguiste fazer...

E' normal ja que ainda nao tenhas percebido o funcionamente de sockets, mas pelo o que dizeste, parece que nao estas muito interesado:

procurei mais de 1000 sites e nada em 'c' ninguém nunca fez tutorial de um servidor com multiplos clientes e difusão de mensagens para a linguagem c e tenha publicado (pelo menos dentro do portugues e ingles).

os exemplo de chat em c que aparecem publicados são ridiculos onde um chat para eles é uma comunicação só entre 1 cliente e 1 servidor, quando um servidor é apenas um meio de comunicação manda mensagens por normalidade automaticas e nunca é um individuo, um cliente.

O servidor e' a parte mais importante numa coneccao de rede... tens este tutorial http://beej.us/guide/bgnet/

Acho que e' umas das razoes que eu gosto de C e' que muita das coisas que queres fazer implica bateres codigo e perceber o que estas a fazer, que contribui muito para a tua aprendizagem, mas claro se queres algo rapido e nao muito complicado de se fazer, tens linguagens para isso.


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
apocsantos

Boa noite,

@Pikax: Esse livro é impecável! Eu já lhe deixei o link para ele 3 vezes neste tópico... :(

Cordiais cumprimentos,

Apocsantos


"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Share this post


Link to post
Share on other sites
pikax

Boa noite,

     @Pikax: Esse livro é impecável! Eu já lhe deixei o link para ele 3 vezes neste tópico... :(

Cordiais cumprimentos,

Apocsantos

E' dos melhores, mas ainda e' preciso ter um pouco de conhecimento de funcionamento de redes.Se bem percebi o que ele queria fazer e' que cada cliente tenha o endereco dos outros cliente, que faz com o que o programa fique com umas falhas de segurancas, sem falar no problema do NAT se ele quisesse funcionar na internet.

2- colocar o servidor a avisar cada cliente da chegado de um novo cliente indicando endereço e o porto dele tambem nessa linha
Nao vejo muito sentido em mandar a porta do cliente, ja que a porta pode ser do router, por isso penso que seja para os clientes ligarem-se entre si.

Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
HappyHippyHippo

só uma coisa, o código do servidor pode parecer muito catita, mas tem uma coisa que a mim faz-me uma comichão tremenda : variáveis globais.


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
apocsantos

Boa noite,

@Pikax: Pelo que percebi ele quer ter um programa servidor, onde se ligam os programas "cliente" tipo IRC, e quando um utilizador manda uma mensagem todos os utilizadores vêm "nick: mensagem". Não é nada do outro mundo, mas requer esforço e paciência! Eu fiz um ano passado. Por sinal também foi trabalho académico e deu algum gosto rever alguma matéria de sockets. Requer conhecimento, mas é como diz o velho ditado "Quem quer bolotas.... trepa para as ir buscar!", que é com quem diz: "Quem quer ser programador, procura aprender a fazer e não a solução já feita".

Pensando nas coisas de forma simples: O cliente não precisa de saber mais nada além de IP e Porta do Servidor. O servidor tem de gerir "quem está ligado e fazer o "broadcast" da mensagem para todos os clientes ligados", quando um cliente se desliga, faz um "broadcast" a informar todos os clientes que o utilizador X se desligou. Em teoria é pensar "como funciona um "Hub".... Se a memória não me falha... Um Hub recebe uma "mensagem" e manda-a para todas as portas que tem". É usar uma estrutura no servidor para armazenar os dados das ligações dos clientes e usar um for para fazer o "broadcast".

Para quê complicar o simples ? A questão da escrita "simultânea" do "ter de bloquear o printf e o scanf", resolve-se bem com a threads usando a lib pthreads.

Cordiais cumprimentos,

Apocsantos


"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Share this post


Link to post
Share on other sites
msmsms

eu percebi grande parte do servidor que deixei eu fiz uma versao minha

Edited by msmsms

Share this post


Link to post
Share on other sites
pikax
é triste ver que alguns já nem se lembras do que é aprender, já não precesiam!

e preferem no lugar de ajudar dar respostas tortas e indirectas so para ajudar a perder tempo.

Eu todos os dias aprendo, tu quase que nao tens duvidas, porque nao sabes trabalhar com sockets, demostra falta de conhecimento da tua parte. O que sabemos nao foi so' atraves de ir a sites e fazer Copy&Paste, tivemos muita pesquisa, tivemos a tentar compreender as coisas, ao contrario de ti, que nem sequer sabes muito bem o que faz o codigo que fizeste...

eu é que obter por tentar fazer o chat uma vez que nao existia e não existe, porque quem sabe fazer esse avanço em c não divulga

Esta a ate' deu para rir, queres a "papinha" toda feita???

eu já percebi que apenas estão a fazer pouco da minha dificuldade e se não querem ajudar comam o vosso conhecimento neste aspecto se é que o têm!

Ninguem fez pouco com a tua dificuldade, tu e' que parece que nao leste os posts do @ApocSantos.

o grande problema na aprendizagem principalmente deste tipo de aprendizagem e que quem consegue saber isto de forma breve são gente que não faz de facto nenhum que pega de facto sempre tudo ja feito através de outras pessoas (que levaram muito tempo a compreender e conseguem simplificar e abreviar as coisas ao partilharem) onde acham tudo facil porque têm mais meios e ai basta decorar formas de resolução (decorar caminhos) que ate se esquecem que sabem isso assim!, grande parte do pessoal da informática são pessoas que não prestam que só sabem criticar e projudicar os outros a quem eu teria muito gosto de lhes cuspir na cara embora lamente bastante que sejam o lixo que são.

Nao sei se ja' reparaste mas estamos num forum de programacao, nos estamos aqui para ajudar porque queremos, nao somos obrigados. Sou adepto de explicar e indicar o melhor caminho que sei, a quem tenha duvidas, mas uma coisa que sou contra e' pessoas que pensam que tem tudo feito ao ir ao google, esses nem querem aprender nem fazer.

ainda assim nao vou desistir do lixo deste chat e quando acabar este lixo (mesmo que seja tarde de mais) vou divulga-lo na porra dos blogs bem comendado passo a passo para para não serem apenas sanguessugas dos outros e EGOÍSTAS! a saber isso.

fazes bem, mas cuidado ao postares o servidor, ja' que pode ter alguma licenca associada...


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
HappyHippyHippo

nenhuma mensagem anterior me fez avançar em quase nada aqui

já te disse (e parece que já percebeste) que o servidor e o cliente estáo a funcionar.

têns é o problema que te referi acima (ao contrário do que dizes) que as mensagens só serão processadas pelo cliente após o "desbloqueio" do scanf, ao enviar uma mensagem.

era algo que se resolvia com threads, mas como não sabes, não vale a pena pensar no problema.

agora, qual é exactamente a tua dúvida/problema ?

já agora, muito dificilmente alguem te dará código, explicar tudo bem, sem problemas, afinal é para isso que o fórum existe, mas estar a bater código, tenho as minhas dúvidas que alguém se disponibilizará para essa tarefa.


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
msmsms

já te disse (e parece que já percebeste) que o servidor e o cliente estáo a funcionar.

têns é o problema que te referi acima (ao contrário do que dizes) que as mensagens só serão processadas pelo cliente após o "desbloqueio" do scanf, ao enviar uma mensagem.

era algo que se resolvia com threads, mas como não sabes, não vale a pena pensar no problema.

agora, qual é exactamente a tua dúvida/problema ?

já agora, muito dificilmente alguem te dará código, explicar tudo bem, sem problemas, afinal é para isso que o fórum existe, mas estar a bater código, tenho as minhas dúvidas que alguém se disponibilizará para essa tarefa.

o meu problema continua a ser aquele que ja tinha desde o inicio fazer o cliente enviar uma mensagem para outro cliente e vise versa

como é que ele vai escrever e receber multiplas mensagem?

Edited by msmsms

Share this post


Link to post
Share on other sites
pikax

a situação é que parece que não percebem que os exemplos que me estão a passar são de um cliente basico que apenas e só envia uma mensagem a um servidor e nunca se transforma em varios

Tu ja tens o servidor que tem uma lista de clientes e ja tem ate' funcoes que tratam de alguma coisa por ti, so' mostra que nao percebes o codigo que sacaste, em multi-client simples como queres basta criares um socket novo para cliente!

Mas pelo o que dizeste(48h sem dormir), em que tiveste a pesquisar e a fazer o client, deixame dizer que nao sabes procurar, tens aqui no forum varios topicos disso!

https://www.portugal-a-programar.pt/topic/55847-duvidas/?do=findComment?comment=473277

www.portugal-a-programar.pt/topic/52878-servers/

conforme, em linux e' uma e em windows e' outra.

Podes fazer com qualquer IDE com o compilador gcc(minGW).

Este codigo esta feito para funcionar em linux, basta fazer algumas alteracoes faceis para ele funcionar em windows, isto e' um cliente - servidor que fiz num teste.

cliente

/****************************************
|  1º TESTE DE AVALIAçãO      17/11/2011
|       Redes de Computadores
|  Nome:                        Nr:
|  Turma:
|         
|     Aluno: 
|   
|     Professor: 
|
|     Avaliação: 
|
|   Escola Secundária D. Afonso Sanches
|   Curso Profissional de Programação
|    e Gestão de Sistemas Informáticos
*****************************************/
//     CLIENTE

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/select.h>
#define NR_CARACTERES 400
#define PORTA 7000


int main(){
   struct hostent *hostip;
   int sock;
   char mensagem[NR_CARACTERES];
   unsigned int tamanho;
   struct sockaddr_in sockaddr;
   int nrOrdem=89;

   /* Insira um comentário apropriado */
   sock=socket(AF_INET, SOCK_STREAM, 0);
   if (sock==-1)
       perror("Socket");


   /* Insira um comentário apropriado */
   sockaddr.sin_family = AF_INET;
   sockaddr.sin_addr.s_addr = INADDR_ANY;
   sockaddr.sin_port = htons(PORTA);


   /* Insira um comentário apropriado */
   if ((hostip = gethostbyname("localhost")) == NULL) {
          puts("Error resolving hostname..");
          exit(1);
   }

   // Preparação do connect() -- NÃO ALTERAR!!!!       
   memcpy(&sockaddr.sin_addr, hostip->h_addr_list[0], hostip->h_length);

   if (connect(sock,(struct sockaddr *) &sockaddr,sizeof(sockaddr)) < 0)
       error("ERROR connecting");


   read(sock,mensagem,NR_CARACTERES);
   printf("sms recebida= %s",mensagem);
   if(mensagem[0]=='a')
   {
   	read(sock,mensagem,NR_CARACTERES);

   	printf("\nsms recebida= %s",mensagem);

   	printf("\nEscreva a mensagem:");
   	gets(mensagem);
   	write(sock,mensagem,NR_CARACTERES);

   	read(sock,mensagem,NR_CARACTERES);
   	printf("\nsms recebida= %s",mensagem); 

   	printf("\nEscreva a mensagem:");
   	gets(mensagem);
   	write(sock,mensagem,NR_CARACTERES);
   }
   else
   {
   	printf("\nEscreva a mensagem:");
   	gets(mensagem);
   	write(sock,mensagem,NR_CARACTERES);   

   	read(sock,mensagem,NR_CARACTERES);
   	printf("\nsms recebida= %s",mensagem); 

   	printf("\nEscreva a mensagem:");
   	gets(mensagem);
   	write(sock,mensagem,NR_CARACTERES);

   	read(sock,mensagem,NR_CARACTERES);
   	printf("\nsms recebida= %s\n",mensagem);   
   }

   close(sock);

   return 0;
}

server

/****************************************
|  1º TESTE DE AVALIAçãO      17/11/2011
|       Redes de Computadores
|  Nome:                        Nr:
|  Turma:
|         
|     Aluno: Carlos David Carvalho Rodrigues
|   
|     Professor: Nuno Pereira 
|
|     Avaliação: 
|
|   Escola Secundária D. Afonso Sanches
|   Curso Profissional de Programação
|    e Gestão de Sistemas Informáticos
*****************************************/
//     SERVIDOR
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/select.h>
#define TAM 400
#define PORTA 7000

int main() {

   int DSCR;
   unsigned int len;
   int new_DSR;
   int new_DSR2;
   char mensagem[TAM];
   /* Comentário nº 1: Insira um comentário de resposta à questão 2.1 */
   struct sockaddr_in address;
   /*********************************************
   **		Comentário nº1-resposta		**
   ** 	A estrutura do sockaddr_in serve para	**
   ** guardar os endereços de IP entre outras 	**
   ** informações necessárias para o computador**
   ** comunicar com o outro.			**
   *********************************************/

   /* Comentário nº 2: Insira um Comentário de resposta à questão 2.2 */
   /*********************************************
   **		Resposta à questão 2.2		**
   **	A função socket irá retornar uma um 	**
   ** "descritor" para identificar o socket se	**
   ** der erro a função irá retornar -1.	**
   *********************************************/

   // Nota: usar opões: AF_INET e SOCK_STREAM,

   DSCR=socket(AF_INET,SOCK_STREAM,0);

   if (DSCR==-1)
       perror("Socket");

   /* Comentário nº 3: Insira um comentário de resposta à questão 4 */
   /*********************************************
   **		Comentário nº3-resposta		**
   ** 	A primeira linha é para identificar a	**
   ** familia a que a estrutura irá utilizar	**
   ** para comunicar com o outro programa, já	**
   ** a segunda é para defenir o IP a que irá	**
   ** se conectar, mas aqui neste código esta-	**
   ** mos a dizer à estrutura que será qualquer**
   ** máquina					**
   *********************************************/
   address.sin_family = AF_INET;
   address.sin_addr.s_addr = INADDR_ANY;
   address.sin_port = htons(7000);

   //bind socket resposta à pergunta 2.4
   if(bind(DSCR, (struct sockaddr *) &address, sizeof (address))== -1)
   {
   	printf("ERROR a fazer bind!\n");
   	close(DSCR);
   	return 1;
   }


   if(listen(DSCR, 1) == -1)
   {
   	printf("ERROR a fazer listen!\n");
   	close(DSCR);
   	return 1;
   }

   //len = sizeof(struct sockaddr_in);

   new_DSR=accept(DSCR,NULL, NULL);
   /* Resposta à questão 2.5 */ 

   if (new_DSR<0)
      perror("Accept");
   mensagem[0]='b';
   write(new_DSR,mensagem,TAM);

   new_DSR2=accept(DSCR,NULL, NULL);

   if (new_DSR<0)
      perror("Accept2");
   mensagem[0]='a';
   write(new_DSR2,mensagem,TAM);

   /* Comentário nº 4: Insira um comentário de resposta à questão 2.7 */
   /*********************************************
   **		Comentárioº4 - resposta		**
   **	Para receber alguma mensagem podemos	**
   ** utilizar várias funções, como o sscanf, 	**
   ** recv, entre outras, aqui utilizei o recv	**
   ** porque achei mais apropriado.		**
   *********************************************/
   /* Resposta à questão 2.6 */ 

   recv(new_DSR, mensagem, TAM, 0);
   write(new_DSR2,mensagem,TAM);

   recv(new_DSR2, mensagem, TAM, 0);
   write(new_DSR,mensagem,TAM);

   recv(new_DSR, mensagem, TAM, 0);
   write(new_DSR2,mensagem,TAM);

   recv(new_DSR2, mensagem, TAM, 0);
   write(new_DSR,mensagem,TAM);



   /* Resposta à questão 2.8 */ 

   close(DSCR);
   close(new_DSR);
    close(new_DSR2);

   return 0;
}

PS: e' preciso executar 2 clientes


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
msmsms

um codigo cliente pode levar select?

para que me deixas te esse exemplo de codigo cliente?

Edited by msmsms

Share this post


Link to post
Share on other sites
pikax

"quem nao sabe e' como quem nao ve"


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
msmsms

"quem nao sabe e' como quem nao ve"

eu testei o teu exemplo e realmente fez troca de mensagem

nao ha forma de eu fazer um chat mais basico mesmo tendo de usar select e as coisas como FD_SET e etc

um chat onde teria apenas o fundamental

1- troca de nome+mensagem entre os clientes

2- avisar todos os clienets que um dado cliente entrou ou saiu

3 - permitir a saida de um cliente da ligação atraves da mensagem quit

///////////////////////////////////////////////////////////////////
// CHAT ENTRE 3 CLIENTES //////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// OBRIGAÇÕES DO SERVIDOR:
// 1 - enviar cada nome de utilizador e cada mensagem recebida para todos os clientes
// 2 - avisar cada cliente sobre a chega de um novo cliente
// 3 - informar cada cliente sobre a saida de um cliente do chat
///////////////////////////////////////////////////////////////////
//	 SERVIDOR
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/select.h>
#define N_CHAR 400 // numero de caracteres para cada
int main() {
unsigned int len;
char mensagem[N_CHAR];
char nome[N_CHAR];
struct sockaddr_in address;
int socket;
// UTILIZADORES RESGISTADOS
int cliente1;
int cliente2;
int cliente3;
	// SINTAXE DO SERVIDOR
if (argc != 2) {
 printf("servidor <porto>>\n");
 exit(-1);
}

porto = atoi(argv[1]); // definir o porto

// criar o socket (meio de comunicação)
socket =socket(AF_INET,SOCK_STREAM,0);

// avisar em caso de erro ao criar o socket
if (socket==-1)
	perror("Socket");

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(porto);

if(bind(socket, (struct sockaddr *) &address, sizeof (address))== -1)
{
	printf("ERROR a fazer bind!\n");
	close(DSCR);
	return 1;
}

if(listen(socket, 1) == -1)
{
	printf("ERROR a fazer listen!\n");
	close(DSCR);
	return 1;
}

cliente1=accept(DSCR,NULL, NULL);
if (cliente1<0)
   perror("Accept");
mensagem[0]='b';
write(cliente1,mensagem,TAM);

cliente2=accept(DSCR,NULL, NULL);

if (cliente2<0)
   perror("Accept2");
mensagem[0]='a';
write(cliente2,mensagem,TAM);
cliente3=accept(DSCR,NULL, NULL);

if (cliente3<0)
   perror("Accept2");
mensagem[0]='a';
write(cliente3,mensagem,TAM);
// troca de mensagens
recv(cliente1, mensagem, N_CHAR, 0); // recv(cliente1, nome, N_CHAR, 0);
write(cliente2,mensagem, N_CHAR);	// write(cliente2,nome, N_CHAR)
recv(cliente2, mensagem, N_CHAR, 0); // recv(cliente2, nome, N_CHAR, 0);
write(cliente1,mensagem,N_CHAR);	 // write(cliente1,nome, N_CHAR)

recv(cliente1, mensagem, N_CHAR, 0); // recv(cliente1, nome, N_CHAR, 0)
write(cliente2,mensagem,TAM);  // write(cliente2,nome, N_CHAR)
recv(cliente2, mensagem, N_CHAR, 0); // recv(cliente2, nome, N_CHAR, 0);
write(cliente1,mensagem,N_CHAR);	 // write(cliente1,nome, N_CHAR)
// para cliente 3 como fica ?????????????????



close(socket);
close(cliente1);
close(cliente2);
close(cliente3);
return 0;
}

Edited by msmsms

Share this post


Link to post
Share on other sites
pikax

1- troca de nome+mensagem entre os clientes

2- avisar todos os clienets que um dado cliente entrou ou saiu

3 - permitir a saida de um cliente da ligação atraves da mensagem quit

Iras que fazer um sistema multi-threaded para os clientes poderem mandar mensagens 'a vontade entre si.

1- Tens a lista dos clientes, quando receberes uma mensagem do cliente vais 'a lista ver qual e' o nome dele.(server)

2- Quando inserires um socket na list, envias uma mensagem a dizer que ele entrou, quando sair da lista, mandas uma mensagem a dizer que saiu.(server)

3- quando o utilizador inserir "quit", "quebras" a ligacao!(client)

Edited by pikax

Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
msmsms

Iras que fazer um sistema multi-threaded para os clientes poderem mandar mensagens 'a vontade entre si.

1- Tens a lista dos clientes, quando receberes uma mensagem do cliente vais 'a lista ver qual e' o nome dele.(server)

2- Quando inserires um socket na list, envias uma mensagem a dizer que ele entrou, quando sair da lista, mandas uma mensagem a dizer que saiu.(server)

3- quando o utilizador inserir "quit", "quebras" a ligacao!(client)

apesar de me ter dado a maluqueira com a tentativa de resolver o problema desta aplicação chat ainda não consegui e ainda não desisti

pelo qual este tópico ainda não se encontra resolvido e espero que no final fique aqui registado essa aplicação chat para que outros possam encontrar e perceber futuramente

- gostaria bastante de saber se para os objectivos do chat que apresentei anteriormente há forma de existir um servidor com um código muito mais simples (não existindo a necessidade de tanta coisa, de tantas funções).

- gostaria também de saber se ao utilizar-mos a função select no código servidor nos vemos obrigados a trabalhar com a função de tempo?

- gostaria de saber da parte de quem me tentou ajudar inicialmente o que consideram que ainda não sei e tenho de saber para a construção desde chat no que diz respeito à programação com sockets.

(eu apenas conheço aquilo que coloquei na minha versão de cliente)

e sei que um cliente deve levar as funções:

Edited by msmsms

Share this post


Link to post
Share on other sites
apocsantos

Boa tarde,

Existe forma de ter um servidor bastante mais simples. No meu caso, que até tenho um feito, tem 397 linhas (com linhas em branco, comentários, etc...), 6 funções no total, incluindo a main() . Por curiosidade o cliente tem 83 linhas.

Na minha opinião falta-te aprender threads, e aprofundar sockets, para conseguires realizar o projecto.

- gostaria também de saber se ao utilizar-mos a função select no código servidor nos vemos obrigados a trabalhar com a função de tempo?
Não entendi a questão... Também não li todo o teu código.

Cordiais cumprimentos,

Apocsantos


"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Share this post


Link to post
Share on other sites
msmsms

Boa tarde,

Existe forma de ter um servidor bastante mais simples. No meu caso, que até tenho um feito, tem 397 linhas (com linhas em branco, comentários, etc...), 6 funções no total, incluindo a main() . Por curiosidade o cliente tem 83 linhas.

Na minha opinião falta-te aprender threads, e aprofundar sockets, para conseguires realizar o projecto.

Não entendi a questão... Também não li todo o teu código.

Cordiais cumprimentos,

Apocsantos

Boa tarde,

Existe forma de ter um servidor bastante mais simples. No meu caso, que até tenho um feito, tem 397 linhas (com linhas em branco, comentários, etc...), 6 funções no total, incluindo a main() . Por curiosidade o cliente tem 83 linhas.

Na minha opinião falta-te aprender threads, e aprofundar sockets, para conseguires realizar o projecto.

Não entendi a questão... Também não li todo o teu código.

Cordiais cumprimentos,

Apocsantos

e não podes partilhar esse feito comigo?

mas 300 e tal linhas é dose

eu estou a ler sobre a função select neste site

http://support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/select.htm

parece que é a função select que selecciona os clientes no servidor de alguma maneira através de cada socket

se eu consegui-se um exemplo completo cliente e servidor eu poderia tentar fazer uma versão minha através dele e tentar torna-lo mais simples e básico só a fazer o que necessito que faça

Share this post


Link to post
Share on other sites
HappyHippyHippo

feito em 1 hora :

notas de implementação :

- feito com UDP >> muito mais simples ...

- compila em linux

- thread a funcionar (escrever "/quit" para terminar tudo)

- não testado com clientes a ligarem-se

razão porque fiz o código :

- já tens um e não parece que vás mudar por um feito por ti

- apresentação de UDP e exemplificação de porque é mais simples o UDP : 1 só socket para tudo, não é necessário accept

- como vês, nem usei o select ...

observações :

- é necessário linkar á biblioteca pthread : -lpthread

- número total de linha >> 264

- Número total de variáveis globais : ZERO

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/select.h>
#include <unistd.h>

#include <pthread.h>

#define MAX_CLIENTS 100
#define BUFFER_SIZE 256

typedef struct AppInfo {
   int on;

   struct {
       int port;
       int socket;
   } server;

   int client_count;
   struct {
       int on;
       struct sockaddr_in address;
   } clients[MAX_CLIENTS];

   pthread_t thread;
} AppInfo;

void app_help();
int app_init(int argc, char ** argv, AppInfo * info);
int app_start(AppInfo * info);
int app_clean(AppInfo * info);

int socket_listen(AppInfo * info);
int socket_send(AppInfo * info, struct sockaddr_in source, const char * buffer);

int client_search(AppInfo * info, struct sockaddr_in address);
int client_add(AppInfo * info, struct sockaddr_in address);
int client_remove(AppInfo * info, struct sockaddr_in address);

void * input_thread(void * info);

int main(int argc, char ** argv) {
   AppInfo info;

   /* read arguments */
   if (app_init(argc, argv, &info) != 0) { app_help(); return -1; }

   /* start server */
   if (app_start(&info) != 0) { app_help(); return -2; }

   /* socket read cicle */
   while (info.on) socket_listen(&info);

   /* cleaning */
   app_clean(&info);

   return 0;
}

void app_help() {
   printf("command: udpserver <port> (default: 10100, min: 1024)\n");
}

int app_init(int argc, char ** argv, AppInfo * info) {
   /* reset app info */
   memset(info, 0, sizeof(AppInfo));
   info->server.port = 10100;

   /* store server port */
   if (argc > 1) {
       info->server.port = strtol(argv[2], NULL, 10);
       if (info->server.port < 1024) {
           printf("Invalid port\n");
           app_help();
           return -1;
       }
   }

   return 0;
}

int app_start(AppInfo * info) {
   struct sockaddr_in address;
   struct timeval tv;

   /* create socket */
   if ((info->server.socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == 0) {
       printf("Socket creation error\n");
       return -1;
   }

   /* bind created socket */
   memset(&address, 0, sizeof(struct sockaddr_in));
   address.sin_family = AF_INET;
   address.sin_port = htons(info->server.port);
   address.sin_addr.s_addr = htonl(INADDR_ANY);
   if (bind(info->server.socket, (struct sockaddr *)&address, sizeof(address)) != 0) {
       printf("Socket binding error\n");
       close(info->server.socket);
       return -1;
   }

   /* set socket timeouts */
   tv.tv_sec = 0;
   tv.tv_usec = 100000000;
   setsockopt(info->server.socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
   setsockopt(info->server.socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));

   /* create input thread */
   if (pthread_create(&info->thread, NULL, input_thread, info) != 0) {
       printf("Thread creation error\n");
       close(info->server.socket);
       return -2;
   }

   return 0;
}

int app_clean(AppInfo * info) {
   /* wait for the input thread to stop/terminate */
   pthread_join(info->thread, NULL);

   /* close the opened socket */
   close(info->server.socket);
}

int socket_listen(AppInfo * info) {
   char buffer[bUFFER_SIZE];
   struct sockaddr_in address;
   int address_size, id;

   /* read data from socket */
   if (recvfrom(info->server.socket, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&address, &address_size) == 0) {
       /* check for a join message */
       if (strncmp(buffer, "/join", 5)) {
           /* try to add client to list */
           if (client_add(info, address) == 0)
               /* broadcast /join */
               socket_send(info, address, buffer);
       /* check for a leave message */
       } else if (strncmp(buffer, "/quit", 5)) {
           /* remove client from list */
           if (client_remove(info, address) == 0)
               /* broadcast /quit */
               socket_send(info, address, buffer);
       } else
           /* simple message to broadcast */
           socket_send(info, address, buffer);
   }

   return 0;
}

int socket_send(AppInfo * info, struct sockaddr_in source, const char * buffer) {
   int id;

   /* registed clients cicle */
   for (id = 0; id < MAX_CLIENTS; id++) {
       /* check if the client is on and is not the sender */
       if (info->clients[id].on &&
           memcmp(&info->clients[id].address, &source, sizeof(struct sockaddr_in)) != 0) {
           /* send message */
           sendto(info->server.socket, buffer, strlen(buffer) + 1, 0, (struct sockaddr *)&info->clients[id].address, sizeof(struct sockaddr_in));
       }
   }

   return 0;
}

int client_search(AppInfo * info, struct sockaddr_in address) {
   int id;

   /* registed clients cicle */
   for (id = 0; id < MAX_CLIENTS; id++) {
       /* check if the client is on and is the searched one */
       if (info->clients[id].on &&
           memcmp(&info->clients[id].address, &address, sizeof(struct sockaddr_in)) != 0) {
           /* return id */
           return id;
       }
   }

   return -1;
}

int client_add(AppInfo * info, struct sockaddr_in address) {
   int id;

   /* check if the list if full */
   if (info->client_count == MAX_CLIENTS) {
       /* message client that the server is full */
       sendto(info->server.socket, "/full", 5, 0, (struct sockaddr *)&address, sizeof(struct sockaddr_in));
       return -1;
   }

   /* registed clients cicle */
   for (id = 0; id < MAX_CLIENTS; id++) {
       /* check if the client is on and is the inserting one */
       if (info->clients[id].on &&
           memcmp(&info->clients[id].address, &address, sizeof(struct sockaddr_in)) == 0) {
           /* ignore a join from a registed client */
           return -2;
       }
   }

   /* registed clients cicle */
   for (id = 0; id < MAX_CLIENTS; id++) {
       /* check if the client is not on */
       if (!info->clients[id].on) {
           /* register the client in the available slot */
           memcpy(&info->clients[id].address, &address, sizeof(struct sockaddr_in));
           info->clients[id].on = 1;
       }
   }
   /* increment the registered client count */
   info->client_count++;

   return 0;
}

int client_remove(AppInfo * info, struct sockaddr_in address) {
   int id;

   /* registed clients cicle */
   for (id = 0; id < MAX_CLIENTS; id++) {
       /* check if the client is on and is the removinf one */
       if (info->clients[id].on &&
           memcmp(&info->clients[id].address, &address, sizeof(struct sockaddr_in)) == 0) {
           /* mark the client as off */
           info->clients[id].on = 0;
           return 0;
       }
   }

   return -1;
}

void * input_thread(void * info) {
   AppInfo * aux = (AppInfo *)info;
   char buffer[bUFFER_SIZE];
   int run = 1;

   /* input cicle */
   while (run) {
       /* read input */
       fgets(buffer, BUFFER_SIZE, stdin);

       /* check for quit command */
       if (strncmp(buffer, "/quit", 5) == 0) {
           /* mark the app and thread to terminate */
           aux->on = 0;
           run = 0;
       }
   }

   return NULL;
}

Edited by HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.