Created
July 21, 2014 15:30
-
-
Save daltheman/1e8df7d10fc0ac7183fe to your computer and use it in GitHub Desktop.
Simple BSD Socket
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.m | |
// simple_echo_server | |
// | |
// Created by Danilo Altheman on 14/07/14. | |
// Copyright (c) 2014 Quaddro (http://www.quaddro.com.br). All rights reserved. | |
// | |
/************ | |
Must READ!!! | |
http://pic.dhe.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtps5%2Fs5tcpcf.html | |
http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#closedown | |
*************/ | |
#import <stdio.h> // Se você não sabe o que significa esta primeira linha, para de ler agora! | |
#import <unistd.h> // para usar a função close. | |
#import <string.h> // para usar o memset. | |
#import <stdlib.h> // para a função exit | |
#import <sys/socket.h> // para o socket | |
#import <sys/types.h> // contem os tipos que iremos utilizar. | |
#import <netinet/in.h> // header do IP | |
#import <arpa/inet.h> // contém as rotinas de manipulacao de end. de IP | |
#import <errno.h> // para gerar erros no Unix. | |
#import <signal.h> // para interceptar o sinal SIGINT control+c | |
int server_fd; | |
void signal_handler() { | |
printf("\nEncerrado pelo usuário\n"); | |
// fecha o socket do servidor. | |
close(server_fd); | |
// Sai com sucesso! | |
exit(0); | |
} | |
int main(int argc, const char * argv[]) { | |
// Descritor de arquivo do socket | |
int client_fd; | |
// Struct que conterá inf. do socket | |
struct sockaddr_in server_addr, client_addr; | |
// Para pegar o tamanho do socket do cliente (veja explicação byte order abaixo), que não sabemos se é little ou big endian | |
socklen_t client_sock_len; | |
// Aqui falamos que o IP utilizará o TCP como transporte. Sintaxe da função: socket(familia, proto_transp, protocolo_enderecamento) | |
// Você pode encontrar a lista de protolocos em: /etc/protocols. Repare que o IP = 0 | |
// Se o retorno da função for igual a zero, é porque deu certo. Qualquer número negativo, deu pau. Veja a manpage para os numeros. | |
if((server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) { | |
perror("Socket"); | |
exit(1); | |
} | |
// Garante que a variável que contera inform. do end. do socket estará limpa (zerada). | |
// Esta função serve para limpar e alocar uma variavel na memoria! | |
memset(&server_addr, 0 , sizeof(server_addr)); | |
// Criando o Socket: | |
// Aqui definimos o tipo de protocolo de endereçamento. INET é abreviação de Internet. | |
server_addr.sin_family = AF_INET; | |
// A constante INADDR_ANY indica que iremos utilizar o IP definido na máquina. htonl = host to network long. | |
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
// Define a porta do socket. htons = host to network short. | |
// Para usar portas abaixo da 1024, você deverá executar o programa com sudo. A lista de portas pode ser encontrada em: | |
// /etc/services | |
server_addr.sin_port = htons(60080); | |
/* | |
Os computadores utilizam duas formas de armazenar dados em memória, o little endian e o big endian. | |
A arquitetura X86 é little endian, porém PowerPC e outras utilizam Big Endian. Para que o programa seja multiplataforma | |
utilizamos as funções de byte order para poder compilar em ambas as arquiteturas. Por isso utilizamos as funções | |
htons e htonl. Veja mais em: | |
http://pt.wikipedia.org/wiki/Extremidade_(ordena%C3%A7%C3%A3o) | |
http://support.microsoft.com/kb/102025/pt-br | |
*/ | |
// A função bind dá um nome a um socket. Quando um socket é criado, ele é associado à familia de endereços, porém não possui um nome. | |
// bind solicita ao kernel que o endereço (IP por exemplo) seja associado ao socket. | |
if ((bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr))) == -1) { | |
perror("Bind"); | |
exit(1); | |
} | |
printf("Aguardando conexões na porta: %d\n", ntohs(server_addr.sin_port)); | |
// Listen diz para o socket começar a "ouvir" ou seja, fica aguardando por conexões. Sintaxe: listen(socket, quant_conexoes_simult) | |
listen(server_fd, 5); | |
// Fica aguardando o usuário digitar ctrl+c, e então chama a função de encerramento do programa. | |
signal(SIGINT, signal_handler); | |
// Entra em loop aguardando e gravando no socket do cliente | |
while (1) { | |
client_sock_len = sizeof(client_addr); | |
// aceita a conexão do cliente e associa as inf. do socket dele a uma variavel. utilizaremos ela para enviar/gravar dados. | |
if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_sock_len)) < 0) { | |
perror("Accept"); | |
} | |
else { | |
printf("Conexão recebida de: %s\n", inet_ntoa(client_addr.sin_addr)); | |
char data[] = "Mussum ipsum cacilds, vidis litro abertis. Consetis adipiscings elitis. Pra lá , depois divoltis porris, paradis. Paisis, filhis, espiritis santis. Mé faiz elementum girarzis, nisi eros vermeio, in elementis mé pra quem é amistosis quis leo. Manduma pindureta quium dia nois paga. Sapien in monti palavris qui num significa nadis i pareci latim. Interessantiss quisso pudia ce receita de bolis, mais bolis eu num gostis.\n"; | |
// Envia dados no socket | |
send(client_fd, data, sizeof(data), 0); | |
printf("Enviando %i bytes de dados: %s\n", (int)sizeof(data), data); | |
// fecha o socket do cliente. | |
close(client_fd); | |
} | |
// inet_ntoa = internet network to address -> IP | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment