Archive for junho, 2008

C chat with sockets and thread

sábado, junho 28th, 2008

I developed a chat server in the C language and Python language
The chat written in Python is posted here. Now I developed the chat using the C sockets and threads.

The code developed in C follows the same principles of the code in Python.
In C had to develop a double linked list to store the file descriptor of the socket, user name and nickname.

This code was developed to the discipline of Distributed Systems.

# # This program is free software; you can redistribute it and/or modify
# #it under the terms of the GNU General Public License as published by
# #the Free Software Foundation; version 2 of the License.
# # This program is distributed in the hope that it will be useful,
# #but WITHOUT ANY WARRANTY; without even the implied warranty of
# #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# #GNU General Public License for more details.
# #
# #author: Marlon Petry
# #Date: 2008/04/30
# #Function: Chat server in C sockets threads
# #
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include

#include  /* for FIONREAD (sigh) */
#include 
#include 
#include “listaDDE.h”
#include 
#define MYPORT 5800    // the port users will be connecting to

#define BACKLOG 10     // how many pending connections queue will hold
#define MAXLINE 1024
#define NUM_THREADS     50
fd_set rmask;
pthread_mutex_t mutexsum;
pthread_mutex_t mutexLogin;
int fd_max;
int maxfds;

int sockfd;
fd_set read_fds;
fd_set master;
nodo *root = NULL;
static int	read_cnt;
static char	*read_ptr;
static char	read_buf[MAXLINE];

static void *sendMensagem(void *arg);
void sigchld_handler(int s);
static void *sendALL(char msg[],int soks);
static void *sendMensagem(void *arg);
static void *newClientConnect(int arg);

void sigchld_handler(int s)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}

void *sendALL(char msg[],int soks)
{
	nodo *aux = getFirst();
	while(aux != NULL)
	{
		int soc =aux->socket;

		if(soc != soks)
			{
	      	       		if(write(soc, msg, strlen(msg)) == -1)
		    			perror(”send”);
				printf(”send %s %s\n”,msg,aux->nick);

			}
		aux = aux->prox;
	}
}

void *sendMensagem(void *arg)
{
  char *buff;
  int fd = (*(int *) arg);
  int nbytes;
  char tmp[5000];

  printf(”\nthread call %d”,fd);
  newClientConnect(fd);
  printf(”\n entry LOOP\n”);

  nodo *cliente = busca(fd);

while(1)
{

     buff = (char *) calloc( MAXLINE,sizeof(char));
     if(FD_ISSET(fd,&master))
     {
         nbytes = recv(fd,buff, MAXLINE -1 , 0);
	 if(nbytes > 1)
	 {

	   if(!tmp)
	   {
		perror(”alocation:”);
		exit(-1);
	   }
           strcat(tmp, cliente->nick);
	   strcat(tmp, ” >> “);
	   strcat(tmp, buff);
           sendALL(tmp,fd);
	 }
	 else
	 {
	       if (nbytes == 0) {
                       printf (”servidor: socket %d desligado\n”,  fd);
               } else {
                       perror (”recv”);
               }
              close (fd); // BYE!!
              FD_CLR( fd , &master);
	      removi(getFirst(),fd);
	      pthread_exit(NULL);
	  }

     }
     free(buff);

}

}

static void *newClientConnect(int arg)
{
	int fd = arg;
	pthread_t tid;
	struct sockaddr_in their_addr;
	char welcome[] = “Welcome Chat SistDistribuidos 0.1 \n”;
	char msg1[] = “Login: “;
	char msg2[] = “NickName: “;
	char nome[100];
	char nick[100];
	int nbytes;
	socklen_t sin_size;

	pthread_mutex_lock (&mutexLogin);

		printf(”\naccept \n”);
		if (write(fd, welcome, sizeof welcome - 1) != sizeof welcome - 1) {
	   		perror(”write:”);
			exit(1);
		}		

		printf(”write %s \n”,welcome);
		usleep(1000);

		if (write(fd, msg1, strlen(msg1)) != strlen(msg1)) {

	   		perror(”write:”);
			exit(1);
		}

		printf(”write %s \n”,msg1);
		usleep(1000);
		if ((nbytes = recv(fd, nome, 100,0)) < 0) {
		perror("read:");
	        exit(1);
	   	return;
		}
		nome[nbytes -1] = '\0';
		printf("Read %d %s\n",strlen(nome),nome);
		usleep(1000);
		if (write(fd, msg2, sizeof msg2 - 1) != sizeof msg2 - 1) {
	        	perror("write:");
	   	exit(1);
		}

		if ((nbytes =recv(fd, nick, 100,0)) < 0) {
	  	perror("read:");
		 exit(1);
		}
		nick[nbytes-1]='\0';
		printf("Read %d %s\n",strlen(nick),nick);		

		inseri(&root,fd,nome,nick, inet_ntoa(their_addr.sin_addr));
		FD_SET(fd, &master);		/* listen to this socket too */

	printf("end welcome \n");

	pthread_mutex_unlock (&mutexLogin);

}

int main(void)
{
      // listen on sock_fd, new connection on new_fd
    int j,new_fd;
struct timeval waitd;
int nbytes;
    char buf[256];
    int fd_max; //numero maximo de descritores

    struct sockaddr_in my_addr;    // my address information
    struct sockaddr_in their_addr; // connector's address information
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;

    FD_ZERO(&master);
    FD_ZERO(&read_fds);

    pthread_mutex_init(&mutexsum, NULL);
    pthread_mutex_init(&mutexLogin,NULL);

    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    if ( setsockopt ( sockfd , SOL_SOCKET , SO_REUSEADDR , &yes , sizeof ( int ) ) == -1 )
    {
		perror ( " setsockopt " );
		exit ( 1 );
    }

    my_addr.sin_family = AF_INET;         // host byte order
    my_addr.sin_port = htons(MYPORT);     // short, network byte order
    my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
    memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);

    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) == -1) {
        perror("bind");
        exit(1);
    }

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    FD_SET(sockfd, &master);

    fd_max = sockfd;	

    int rc =0;	 

    int i = 0;
    int ret;

    int fd;
      waitd.tv_sec = 1;
      waitd.tv_usec = 0;

     while(1)
     {  

        read_fds = master;
        if (select (fd_max+1,  &read_fds, NULL, NULL, NULL)== -1) {
                perror ("select");
                exit(1);
        }

        int addrlen = sizeof (their_addr);
        if (( new_fd = accept(sockfd,&their_addr,&addrlen)) == -1)  {
            perror ("accept");
        } else {

            FD_SET ( new_fd , &master);

            printf ("server : new connection %s socket %d\n",
                              inet_ntoa (their_addr.sin_addr),new_fd);

	    pthread_t tred;
	    rc = pthread_create( &tred, NULL,sendMensagem, (void *) &new_fd);
       	    if (rc){
        	printf("ERROR; return code from pthread_create() is %d\n", rc);
       		exit(-1);
            }

        }
      } 

pthread_mutex_destroy(&mutexsum);
pthread_mutex_destroy(&mutexLogin);

    return 0;
}

Header Double Linked List name ListaDDE.h

# #!/usr/bin/env python
# # -*- coding: iso-8859-1 -*-
# # This program is free software; you can redistribute it and/or modify
# #it under the terms of the GNU General Public License as published by
# #the Free Software Foundation; version 2 of the License.
# # This program is distributed in the hope that it will be useful,
# #but WITHOUT ANY WARRANTY; without even the implied warranty of
# #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# #GNU General Public License for more details.
# #
# #author: Marlon Petry
# # 

#include 
#include 
#include 
#define MAXBUFFER 2048

typedef struct cel
{
	int socket;
	char nome[50];
	char nick[50];
	char host[50];
	char buff[MAXBUFFER];
	struct cel *ante;
       	struct cel *prox;
}nodo;

nodo *getFirst();
nodo *getLast();
void inseri(nodo **root, int socket,char nome[],char nick[],char host[]);
void removi(nodo *root, int socket);
void print (nodo *ini);

Implementation Double Linked List without use global variable

# #!/usr/bin/env python
# # -*- coding: iso-8859-1 -*-
# # This program is free software; you can redistribute it and/or modify
# #it under the terms of the GNU General Public License as published by
# #the Free Software Foundation; version 2 of the License.
# # This program is distributed in the hope that it will be useful,
# #but WITHOUT ANY WARRANTY; without even the implied warranty of
# #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# #GNU General Public License for more details.
# #
# #author: Marlon Petry
# #Date: 2008/04/30  

#include 
#include 
#include 
#include “listaDDE.h”
nodo *first = NULL, *last = NULL;

nodo *getFirst()
{
	printf(”call getFirst()\n”);
	return first;
}

nodo *getLast()
{
	return last;
}
void inseri(nodo **root, int socket, char nome[],char nick[],char host[])
{
	nodo *aux;
	//primeira inserção
	if(*root == NULL)
	{
		*root = (nodo *) malloc(sizeof (nodo));
		if(*root == NULL)
		{
			perror(”erro de alocação\n”);

		}
		(*root)->socket = socket;
		strcpy((*root)->nome , nome);
		strcpy((*root)->nick , nick);
	        strcpy((*root)->host , host);
		(*root)->prox = NULL;
		(*root)->ante = NULL;
		 first = (*root);
		last = first;

	}
	else
	{
		aux = (nodo *) malloc(sizeof (nodo));
		if(aux == NULL)
		{
			perror(”erro de alocação\n”);

		}
		aux->socket = socket;
		strcpy(aux->nome , nome);
		strcpy(aux->nick , nick);
	        strcpy(aux->host , host);

		aux->ante =last;
            	aux->prox = NULL;

                last->prox = aux;
            	last = aux;
		*root = last;
	}
}

void removi(nodo *primeiro,int dado)
{
   nodo *aux = primeiro;
   while(aux != NULL)
   {
       if(dado == aux->socket && aux == first) //Remove first element
      {

	 if(aux->prox != NULL)
	 {
		printf(”!= null\n”);
		aux->prox->ante = NULL;
	        first = aux->prox;
	 }
	 else
	 {
		printf(”null\n”);
		free(first);

		break;
	 }

      }
      else if(dado == aux->socket && aux->prox == NULL) //remove last
      {
      	 aux->ante->prox = NULL;
         last = aux->ante;
         free(aux);
         break;
      }
      else if(dado == aux->socket && aux->prox != NULL && aux->ante !=NULL) //remove middle
      {
      	aux->ante->prox = aux->prox;
         aux->prox->ante = aux->ante;
         free(aux);
         break;
      }

      aux = aux->prox;
   }
}

void print (nodo *ini)
{
   nodo *p = first;
   while(p != NULL)
   {   printf (”socket %d cliente %s\n”, p->socket,p->nome);
	p = p->prox;    

   }
}

nodo *busca (int key)
{
   nodo *p = getFirst();
   int flag = 0;
   while(p != NULL)
   {
   	if(p->socket == key)
	{
		return p;
	}
	p = p->prox;    

   }
   return NULL;
}

In order to compile this code together use the follow command

gcc -o chatserver server.c listaDDE.c -lpthread

Using

On the server
./chatserver

On the client
telnet ipServer 5800

Digg if you like it:
Development of a chat with the C sockets and Threads

Quantos Computadores tem no Mundo ?

sábado, junho 28th, 2008

Uma recente pesquisa realizada pela Gartner informa que o número de computadores pessoais em todo o mundo já ultrapassou o marco de um bilhão de unidades e também que em 2014 teremos 2 bilhões de máquinas.
Fazendo uma relação com o número de habitantes do mundo que está aproximadamente em 6 bilhões de pessoas temos 1 computador para cada 6 pessoas.
A pesquisa ainda revela que esse crescimento acontecerá em países emergentes como BRASIL, Rússia, Índia e China.
Geralmente escutamos as pessoas falando que querem comprar um computador para ter acesso a internet, conectarem-se ao resto do mundo. Para que a conexão desejada seja possível a infra-estrutura de redes terá dobrar para suprir esta necessidade. Dobrar a capacidade também significa aumentar o número de profissionais na área de informática. Notamos que tudo terá que ser duplicado até 2014, ou seja, em 6 anos.

(more…)

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!

quarta-feira, junho 25th, 2008

…e também a pen drives, card drives, camisetas geeks, livros e mais! O BR-Linux e o Efetividade lançaram uma campanha para ajudar a Wikimedia Foundation e outros mantenedores de projetos que usamos no dia-a-dia on-line. Se você puder doar diretamente, ou contribuir de outra forma, são sempre melhores opções. Mas se não puder, veja as regras da promoção e participe - quanto mais divulgação, maior será a doação do BR-Linux e do Efetividade, e você ainda concorre a diversos brindes!

Ponteiros para Funções

segunda-feira, junho 23rd, 2008

Ponteiros para funções é algo extremamente interessante, eficiente e elegante. Pode ser usado para substituir switch-case, definir em tempo de execução qual função deve ser chamada ou implementar callbacks.

Ponteiros para funções são na realidade ponteiros que apontam para o endereço de uma função. Uma função possui um endereço de memória. Quando o programa é executado todo seu conteúdo é colocado na memória, então uma função é como um variável do tipo inteira, nada mais que um endereço de memória.

(more…)

Balanceando 2 links no Linux

domingo, junho 22nd, 2008

Nesta matéria pretendo mostrar como fazer balanceamento entre links, utilizando uma máquina com o Linux instalado.

A imagem abaixo mostra a topologia de rede, nesta configuração temos uma Linux Box com três
placas de redes eth1 para os clientes, eth0 para o link1 e eth2 para o link2. O link1 é 2 vezes mais rápido que o link2.
balaceamento de links na internet

Existem várias técnicas que podem realizar balanceamento entre links como por exemplo: bonding, roteamento avançado. Irei utilizar roteamento avançado porque com port bonding não descobri como configurar o peso de cada link.

Bonding

Este método permite criar uma uma interface lógica de rede que agrega dois ou mais links físicos conectados a switchs separados. Mais detalhes sobre bonding

Roteamento avançado Linux

Linux possui recursos avançados para roteamento esses recursos estão implementados no kernel, então eles devem estar habilitados. Para saber mais sobre roteamento avançado acesso http://lartc.org/lartc.html

Então vamos colocar a mão na massa.

Pré-requisitos

Kernel

As seguintes opções devem estar habilitadas:

  • CONFIG_IP_ADVANCED_ROUTER (Networking/IP: Advanced Router)
  • CONFIG_IP_MULTIPLE_TABLES (Networking/IP: policy routing)

Estas opções habilitam o roteamento avançado e também possibilitam ter múltiplas tabelas de roteamento.

Para verificar se o seu kernel está compilado com estes recursos rode o seguinte comando:

grep -e CONFIG_IP_ADVANCED_ROUTER -e CONFIG_IP_MULTIPLE_TABLES /usr/src/linux/.config
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y

Se estes recursos não estiverem habilitados será necessário recompilar o kernel habilitando estes recursos. Rode os seguintes comandos para recompilar o kernel com estas opções.

cd /usr/src/linux
make menuconfig

Navegue para Network–>
Network Options –> e modifique as opções
IP: Advanced router para [*] e
IP: policy routing para [*]

Salve e rode make && make modules_install

IPROUTE2

Verifique se o iproute2 está instalado com o comando ip. Caso não esteja instalado neste site possui uma ótima documentação sobre o iproute2.

Definindo a tabela de Rotas

Vamos criar duas tabelas de rotas dentro do arquivo /etc/iproute/rt_tables

echo "1 Link1" >> /etc/iproute/rt_tables
echo "2 Link2" >> /etc/iproute/rt_tables

A partir de agora temos três tabelas de rotas Link1 e Link2.

A próxima etapa é preencher a tabela de rotas.

Rota Link1

/sbin/ip route add 200.xx.yy.0/24 dev eth0 src 200.xx.yy.2 table link1
/sbin/ip route add default via 200.xx.yy.1 table link1
/sbin/ip rule add from  200.xx.yy.2 table link1

Rota Link2

/sbin/ip route add 190.xx.yy.0/24 dev eth0 src 190.xx.yy.2 table link2
/sbin/ip route add default via 190.xx.yy.1 table link2
/sbin/ip rule add from  190.xx.yy.2 table link1

Balanceando

Para balancear o uso dos links devemos atribuir o peso de cada link. O peso é atribuído através do parâmetro weight no nosso exemplo vamos utilizar o peso 2 para o link1 e 1 para o link 2.

/sbin/ip route add default scope global\
         nexthop via 200.xx.yy.1 dev eth0 weight 2\
         nexthop via 190.xx.yy.1 dev eth1 weight 1

Script completo

#!/bin/bash
#
#Script para balanceamento de 2 links de acesso a internet
#Licença=GPL
#Author=Marlon Petry

NETMASK1=200.xx.yy.0/24
DEVICE1=eth0
IPADDRESS1=200.xx.yy.2
GATEWAY1=200.xx.yy.1
TABLE1=Link1

NETMASK2=190.xx.yy.0/24
DEVICE2=eth2
IPADDRESS2=190.xx.yy.2
GATEWAY2=190.xx.yy.1
TABLE2=Link2

#PESO DOS LINKS
W1=2
W2=1

#interface 1
/sbin/ifconfig eth0 down
/sbin/ifconfig eth0 $IPADDRESS1/29  up
/sbin/ip route add $NETMASK1 dev $DEVICE1 src $IPADDRESS1 table $TABLE1
/sbin/ip route add default via $GATEWAY1 table $TABLE1
/sbin/ip rule add from $IPADDRESS1 table $TABLE1

#Interface 2
/sbin/ifconfig eth2 down
/sbin/ifconfig eth2 $IPADDRESS2/29 up
/sbin/ip route add $NETMASK2 dev $DEVICE2 src $IPADDRESS2 table $TABLE2
/sbin/ip route add default via $GATEWAY2 table $TABLE2
/sbin/ip rule add from $IPADDRESS2 table $TABLE2

#Adicionando as rotas e o balanceamento de carga
/sbin/ip route add default scope global\
         nexthop via $GATEWAY1 dev $DEVICE1 weight $W1\
         nexthop via $GATEWAY2 dev $DEVICE2 weight $W2

echo "Balanceamento 2 link petryx.blogrs.com.br"

O balanceamento de links através de roteamento funciona bem, mas segundo o how-to http://lartc.org/lartc.html não é perfeito, pois as rotas são cacheadas. Isto significa que quando um site for acessado através do link1, sempre será acessado através da mesma rota. Este problema pode ser resolvido com a aplicação de um patch disponível no site http://www.ssi.bg/~ja/#routes.

Precisando de Consultoria em Linux entre em contato aqui.

Saiba mais

http://www.linuxhorizon.ro/iproute2.html
http://lartc.org/lartc.html
http://linux-ip.net/html/routing-intro.html
http://www.rnp.br/newsgen/0201/roteamento_linux.html
http://www.linuxjournal.com/article/5826

Por dentro do /proc em Linux

sexta-feira, junho 13th, 2008

O diretório /proc é um Virtual File System criado pelo kernel em memória. Com ele é possivel ver o estado dos processos alterar parâmetros do kernel em tempo de execução.

Irei mostrar alguns recursos interessantes:

Informações da bateria

$cat /proc/acpi/battery/BAT1/info
present:                 yes
design capacity:         2000 mAh
last full capacity:      1375 mAh
battery technology:      rechargeable
design voltage:          14800 mV
design capacity warning: 200 mAh
.
.
.

(more…)

Exportando o X Como fazer

sexta-feira, junho 13th, 2008

Exportar o servidor X no Linux é uma tarefa simples que permite uma máquina sem ambiente gráfico usar o X (servidor gráfico) de outra máquina através da rede.

O ambiente gráfico no Linux é gerenciado pelo servidor gráfico conhecido como X. Este servidor permite ter displays remotos este recurso pode ser interessante para usar em servidores pois como política de segurança o ambiente gráfico não é instalado.

(more…)

Carro de Alta Tecnologia BMW

sexta-feira, junho 13th, 2008

Já pensou você dirigindo uma máquina dessas

Na procura de novos materiais a BMW desenvolveu o GINA Light Visionary Model, visando leveza e praticidade. Mas o detalhe que este carro tem a carroceria feita de pano.

Completamente maleável e prático, o tecido se molda, literalmente, no carro: Sua carroceria muda de forma graças a cabos de alta resistência e barras de fibra de carbono.

As coisas mais curiosa no GINA - sigla em alemão para Geometria e Funções Adaptativas - são os faróis e as portas: seus faróis dianteiros ficam escondidos por baixo do tecido, e quando abertos fazem um movimento similar ao abrir dos olhos humanos e suas portas quando abertas mostram o tecido enrugado ao lado do veiculo.

Leia a máteria completa no BizRevolution

Melhorando imagens com java

quarta-feira, junho 11th, 2008

Geralmente as imagens podem ter ser contraste melhorado realçando partes da imagem que antes não muito destacadas uma forma de melhorar é através da equalização do histograma.

O histograma de uma imagem é demonstrado através de um gráfico de barras, onde é feito um somatório da ocorrência de cada pixel. Neste exemplo será utilizada uma imagem na escala de cinza com um resolução de 16bits (0 a 65536).

Desenvolvi um algoritmo que cria e equaliza o histograma.

(more…)

Por dentro do JOB em Linux

terça-feira, junho 10th, 2008

Jobs em linux estão relacionados as tarefas que são executadas no sistema operacional, mas como ter controle sobre eles ?

Linux é um sistema operacional multitarefa diferente do nosso antigo conhecido MS-DOS. O linux roda mais que um processo por vez, de fato se pensarmos um pouco, o primeiro programa a ser executado é o init, sendo o pai de todos os processos futuros. Este conceito pode ser visualizado através do comando pstree, veja uma parte do resultado:

(more…)