Skip to content

Instantly share code, notes, and snippets.

@marioluan
Last active April 18, 2019 00:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marioluan/7863399 to your computer and use it in GitHub Desktop.
Save marioluan/7863399 to your computer and use it in GitHub Desktop.
Implementação de um servidor socket local em linux.
Compile os arquivos:
$ gcc -o executavel_server socket_server.c
$ gcc -o executavel_client socket_client.c
Inicie o server:
$ ./executavel_server
Rode o client:
$ ./executavel_client
// se conecta a um server
// e loga mensagens
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
int main(){
// endereco
struct sockaddr_in EndLocal;
// descritor, tamanho e retorno do connect
int sockfd, len, retorno;
// armazenara o conteudo retornado
char buffer[1000];
// abre o socket
sockfd = socket(PF_INET, SOCK_STREAM, 0);
// tamanho do endereco atribuido ao socket
len = sizeof(EndLocal);
// cleanup
memset((struct sockaddr_in *)&(EndLocal), 0, len);
// dominio do socket
EndLocal.sin_family = PF_INET;
// porta
EndLocal.sin_port = htons(4040);
// endereco IP
EndLocal.sin_addr.s_addr = inet_addr("127.0.0.1");
// tenta se conectar ao server
retorno = connect(sockfd, (struct sockaddr*)&EndLocal, len);
if ( retorno != 0 ) {
perror( "Não foi possível se conectar" );
exit(1);
}
// recebe a mensagem do server
recv(sockfd, &buffer, sizeof(buffer), 0);
// loga a mensagem recebida
printf("%s\n", buffer);
// fim do programa
exit(0);
}
// sobe um server na porta 4040
// responde uma mensagem estatica
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
int main(){
// enderecos
struct sockaddr_in EndLocal, EndRemoto;
// descritores, retorno e lens
int sockfd_server, len, retorno;
int sockfd_cliente, lenRemoto;
// mensagem
char *buffer;
buffer = malloc(sizeof(char)*100);
// abre um socket
sockfd_server = socket(PF_INET, SOCK_STREAM, 0);
// tamanho do endereco atribuido ao socket do server
len = sizeof(EndLocal);
// cleanup
memset((struct sockaddr_in *)&(EndLocal), 0, len);
// seta a familia/dominio/escopo do socket
EndLocal.sin_family = PF_INET;
// seta a porta que ficara escutando por conexoes
EndLocal.sin_port = htons(4040);
// seta o endereco IP
EndLocal.sin_addr.s_addr = inet_addr("127.0.0.1");
// atribui o endereco ao socket
retorno = bind(sockfd_server, (struct sockaddr*)&EndLocal, len);
// caso erro, retorna
if ( retorno == -1 ) exit(0);
// escuta por conexoes
// 5 -> tamanho max. fila espera por uma conexao
listen(sockfd_server, 5);
// loga uma mensagem antes de comecar a processar conexoes
printf("%s\n", "Aguardando conexoes na porta:4040" );
// loop infinito
while(1){
// bloqueia a execucao do programa, ate que exista um pedido de conexao por parte do cliente
sockfd_cliente = accept( sockfd_server, (struct sockaddr *) &EndRemoto, &lenRemoto );
// armazena uma string para ser enviada ao cliente
buffer = "Cliente se conectou no servidor!\n";
// envia para o cliente os dados, seguido do tamanho total de dados sendo enviado
// 0 -> opcional, flags
send(sockfd_cliente, buffer, strlen(buffer), 0);
// fecha a conexao com o cliente
close(sockfd_cliente);
}
}
@manuwell
Copy link

No server.c faltou os includes:

#include <arpa/inet.h>
#include <unistd.h>

E no client.c faltou o

#include <arpa/inet.h>

@manuwell
Copy link

A declaração da var lenRemoto não pode ser int, tem que ser:

socklen_t lenRemoto;

Segundo a lib socket, method, accept:

accept(int socket, struct sockaddr *address,
             socklen_t *address_len);

http://pubs.opengroup.org/onlinepubs/7990989799/xns/syssocket.h.html

@marioluan
Copy link
Author

Sem fazer as modificações, compila :P. Agora, sabe o porque? Será que tem alguma lib que é incluída por default (arp.*, por exemplo)?

@marioluan
Copy link
Author

marioluan commented Jul 23, 2016

Sobre o socklen_t, eu peguei a assinatura do método de um livro (dai o uso do int) :P, parece que de int, mudou pra size_t (quebrou a compatibilidade) e depois fizeram um socklen_t, que é apenas um "proxy"/compativel para int.

Se liga:
Quoting Linus Torvalds:

"Any sane library must have "socklen_t" be the same size as int.
Anything else breaks any BSD socket layer stuff. POSIX initially did
make it a size_t, and I (and hopefully others, but obviously not too
many) complained to them very loudly indeed. Making it a size_t is
completely broken, exactly because size_t very seldom is the same
size as "int" on 64-bit architectures, for example. And it has to be
the same size as "int" because that's what the BSD socket interface
is. Anyway, the POSIX people eventually got a clue, and created
"socklen_t". They shouldn't have touched it in the first place, but
once they did they felt it had to have a named type for some
unfathomable reason (probably somebody didn't like losing face over
having done the original stupid thing, so they silently just renamed
their blunder)."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment