Jump to content
Richard597

Socket em C

Recommended Posts

Richard597

Bom dia, pessoal do portugal a programar!

Pessoal, estou com o caso sobre programacao de socket em C que não estou conseguindo endetender. Se alguém puder me expliicar eu agradeço...

Primeiro observem o código a seguir:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
/* headers necessário para o socket*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT 2000

int main(){
int Mysocket;
struct sockaddr_in Myserv;		 //###<<< observe esta estrutura.

Mysocket = socket(AF_INET, SOCK_STREAM, 0); //criando o sockfd (descriptor)
if (Mysocket == -1){
 perror("socket ");
 exit (1);
 }

Myserv.sin_family = AF_INET; // host byte order
Myserv.sin_port = htons(PORT); // short, network byte order

memset(Myserv.sin_zero, 0x0, 8); // zero the rest of the (definida em string.h)

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

listen(Mysocket, 1);

getc(stdin);

close(Mysocket);
printf("\tSocket Finished...\n\n");
return 0;
}

O problema que estou tendo com este código é na estrutura "struct sockaddr_in Myserv;". Pois notem que ela está declarado dentro da função main(). Porém, quando compilo este código, eu noto que a função bind() retorna -1, pois o perror("bind "); no segundo if é executado.

Mas, por outro lado, quando eu coloco aquela estrutura "struct sockaddr_in Myserv;" fora da função main() e recompilo o código, vejo que o bind() não retorna -1, o programa segue até o final.

Alguém poderia explicar o por quê isto está acontecendo?? (uso compilador gcc no ubuntu).

Edited by Richard597

Share this post


Link to post
Share on other sites
pwseo

Não é suposto preencheres o campo .sin_addr.s_addr da tua variável Myserv?

De qualquer modo, como não o preenches explicitamente, acontece o seguinte:

  • Se definires a variável dentro da main(), o seu valor será escolhido ao acaso
  • Se definires a variável fora da main(), o seu valor será inicializado a zero (pois é isto que acontece a todas as variáveis em C definidas globalmente, fora de funções

Mais ainda, se definires a variável dentro da main e depois colocares .sin_addr.s_addr a zero, o programa funciona.

PS.: Não percebo muito de sockets, mas parece-me que aqui estás a inicializar mal as coisas.

Share this post


Link to post
Share on other sites
Richard597

OK! Valeu pela explicação com relação ao global e ao local.

Mas, em alguns códigos que que eu fiz, também coloquei a estrutura dentro da main() e funcionou!!! O problema foi só nesse código que coloquei aí.

E com relação ao .sin_addr.s_addr, não coloquei em zero e deu certo com os outros códigos.

Agora, em alguns livros que lí, eles indicam colocar o seguinte:

memset(Myserv.sin_zero, 0x0, 8);

Segundo eles, isso serve para resetar o restante da estrutura sockaddr_in

Mas não sei, ao certo, qual é o propósito disto.

De qualquer forma vou seguir essa tua orientação de "Zerar" o .sin_addr.s_addr para ver se dar certo.

Eu não quiz definir o endereço para socket porque eu estou fazendo o teste localmente e usando nc na porta de escuta do socket e o nmap tmabém para scanear a porta...

De qualquer forma, Obrigado pelas dicas... Até breve!!!

Edited by Richard597

Share this post


Link to post
Share on other sites
pwseo

A chamada ao memset não coloca .sin_addr.s_addr a zero, apenas faz isso ao campo .sin_zero.

E se o objectivo é testar localmente, então o melhor é definir o IP como o 127.0.0.1.

Share this post


Link to post
Share on other sites
Richard597

Mas é porque nesse exemplo que fiz, o socket fica só na escuta, aguardando a conexão na porta 2000... Eu ainda não estou configurando ele para aceitar ou entra em conexão remota..

Mas por via das dúvidas eu usei o seguinte:

.sin_addr.s_addr = INADDR_ANY;

Share this post


Link to post
Share on other sites
pwseo

Richard597,

O IP é sempre definido, quer queiras quer não. O que pode acontecer é deteres um IP com um significado especial, como o 0.0.0.0 ou o 127.0.0.1.

Fiz uma modificação ao teu código para me mostrar em que endereço ele está à escuta quando o iniciamos, repara:

~ $ # versão com Myserv dentro da main()
~ $ ./test1
Listening on 253.127.0.0:2000
bind : Cannot assign requested address
~ $ 
~ $ # versão com Myserv fora da main()
~ $ ./test2
Listening on 0.0.0.0:2000

A primeira versão falha porque como .sin_addr não foi inicializado, existe lá um valor que o programa assume como sendo o IP onde queres receber ligações. Como esse não é o teu IP, o programa falha. Na segunda versão esse valor é definido para 0, que é convertido no IP 0.0.0.0, permitindo que o programa funcione.

Share this post


Link to post
Share on other sites
HappyHippyHippo

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

/* headers necessário para o socket*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT 2000

int main() {
int my_socket; // socket descriptor
struct sockaddr_in my_address; // endereço a que o socket irá se associar

my_socket = socket(AF_INET, SOCK_STREAM, 0); // pedir ao sistema para criar o socket
if (my_socket == -1) { // verificar se o pedido foi bem sucedido
perror("socket ");
exit (1);
}

memset(&my_address, 0, sizeof(my_address)); // a inicialização a zero deverá ser feita agora

my_address.sin_family = AF_INET; // -- host byte order -- ???
// isto é a definição do tipo de endereço, que neste caso é AF_INET<->IPv4
my_address.sin_port = htons(PORT); // -- short, network byte order -- ??
// isto é a porta em que o socket será "pendurado"
my_address.sin_addr.s_addr = INADDR_ANY; // <----- o que te disseram para fazer

/* já foi dito que isto não faz sentido
memset(Myserv.sin_zero, 0x0, 8); // zero the rest of the (definida em string.h)
*/

// pedir ao sistema para associat o socket criado ao endereço pretendido
if (bind(my_socket,
(struct sockaddr *) &my_address,
/* sizeof(struct sockaddr) */ sizeof(my_address)) == -1) { // cuidado !! passar o valor correcto do tamanho do endereço !!!
// quanto muito seria "sizeof(struct sockaddr_in)"
perror("bind ");
exit(1);
}

// registar o socket para receber ligações externas
listen(my_socket, 1);

// "flavour" para manter a consola aberta e/ou manter a aplicação aberta
getc(stdin);

// limpeza
close(my_socket);
printf("\tSocket Finished...\n\n");

return 0;
}
[/Code]

Edited by HappyHippyHippo

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

Share this post


Link to post
Share on other sites
Richard597

Ok! Pessoal!

pwseo Obrigado pelo as explicação... E HappyHippyHippo valeu por deixar o código mais claro...

É porque essas coisas de programação, eu fico aqui tentando aprender por conta própria. Nunca frequentei cursos relacionado à computação e, por isso, não aprendi cada coisa por vez (no devido momento). Aí sempre surge essas dúvidas..

Mais uma vez! obrigado a vocês.

Edited by pwseo
nome de utilizador corrigido

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.