Sie sind auf Seite 1von 9

1

Les Sockets en C pour utiliser ces primitives il faudra obligatoirement inclure les bibliothques suivantes dans votre programme : #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> Les structures de donnes : Cette structure permet de stocker les informations sur les adresses des sockets utiliss struct sockaddr { unsigned short sa_family; // la famille dadresse char sa_data[14]; // 14 octets pour ladresse du protocole }; La famille de protocole essentiellement utilise est : AF_INET struct sockaddr_in { short int sin_family; // Famille dadresse unsigned short int sin_port; // le numero de port struct in_addr sin_addr; // Adresse IP unsigned char sin_zero[8]; // non utilis }; In signifie Internet. Cette structure permet en plus de preciser le numro de port decoute ainsi que ladresse du serveur. La structure sockaddr_in peut tre caste en une structure de type sockaddr struct in_addr { unsigned long s_addr; }; Cette structure permet de stocker ladresse IP dune machine Les fonction de conversion de donnes (byte ordering) htons() "Host to Network Short" htonl() "Host to Network Long" ntohs() "Network to Host Short" ntohl() "Network to Host Long" Rcupration de ladresse Ip dune machine Si vous voulez stocker ladresse IP dune machine dans la structure sockaddr_in Utilisez la fonction inet_addr() exemple : Vous avez cette dclaration : struct sockaddr_in adresseIP ; adresseIP.sin_addr.s_addr=inet_addr(192.168.1.1) la fonction inet_addr convertit ladresse IP en un bloc doctets ordonn lisible sur le reseau. Elle retourne -1 si erreur. On peut galement utiliser la fonction inet_aton la place de inet_addr.

2
aton veut dire ascii to network. Permet de rcuprer ladresse Ip sous forme de chaine de caractre et de le mettre dans un format rseau. int inet_aton(const char *cp, struct in_addr *inp); Exemple dutilisation de inet_aton : struct sockaddr_in my_addr; my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT);// entire court vers rseau inet_aton("10.12.110.57", &(my_addr.sin_addr)); memset(&(my_addr.sin_zero), \0, 8); //met a zero le reste de la structure Si vous voulez affichez ladresse IP dune machine il suffit dutiliser la fonction inet_ntoa. Ntoa veut dire network to ascii. Ntoa renvoie ladresse IP sous forme de chaine de caractre. Exemple dutilisation : printf("%s", inet_ntoa(adresseIP.sin_addr)); char *a1, *a2; . . a1 = inet_ntoa(ina1.sin_addr); // this is 192.168.4.14 a2 = inet_ntoa(ina2.sin_addr); // this is 10.12.110.57 printf("address 1: %s\n",a1); printf("address 2: %s\n",a2); Les primitives de base des sockets Le primitive socket : Elle permet de crer une socket et renvoie son descripteur int socket(int domain,int type, int protocol) l'entier renvoy par la primitive socket est le descripteur de la socket cre. Elle renvoie la valeur -1 s'il y'a erreur. Domain : reprsente la famille de protocole utilise. Dans notre cas la famille de protocole internet qui sera utilise : AF_INET. type : reprsente le type de socket utiliser. Il y'a deux types de socket, les sockets en mode flux (SOCK_STREAM) pour une communication en mode connect et les sockets en mode datagramme (SOCK_DRAM) pour la communication en mode non connect. Protocol : reprsente le protocole de niveau transport utiliser. Sa valeur par dfaut est 0. le fait de mettre 0 la place du champ protocol permet de dire a la primitive socket de dtecter automatique le protocole de transport utiliser en fonction du type de socket. La primitive bind : int bind(int sockfd, struct sockaddr *my_addr, int addrlen); Il permet de definer le port dcoute du serveur ainsi que les adresses IP valides du serveur. Sockfd est le descripteur de la socket renvoy par la primitive socket(). My_addr est un pointeur sur la structure contenant , la famille dadresse de la socket, ladresse IP du serveur ainsi que le numro de port dcoute du serveur. addrlen represente la longueur en octet de la structure sock_addr il peut etre obtenu en utilisant loperateur sizeof.

3
Exemple dune portion de programme : #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #define MYPORT 3490 main() { int sockfd; struct sockaddr_in my_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); my_addr.sin_addr.s_addr = inet_addr("10.12.110.57"); memset(&(my_addr.sin_zero), \0, 8); bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)); . . Deux remarques importantes avec bind : my_addr.sin_port = 0; // vous demandez a bind de choisir pour vous un numero de port. La valeut choisie sera arbitraire. my_addr.sin_addr.s_addr = INADDR_ANY; // bind utilisera toutes les addresses valide de la machine lors des ecoutes

4
Laprimitivesendtoetrecvfrom Elles sont utilises en mode non connect pour lenvoie et la rception des donnes int sendto(int sockfd, const void *msg, int len, unsigned int flags,const struct sockaddr *to, int tolen); int recvfrom(int sockfd, void *buf, int len, unsigned int flags,struct sockaddr *from, int *fromlen);

recvfrom renvoie -1 en cas derreur sinon elle renvoie le nombre doctets reus (de meme que sendto). Lesprimitivesdegestiondenom Pourutilisercesprimitives,ilfautdisposerdunservicedenomsurler seau.Maispourdestestsenlocal, onpourrajusteutiliserlefichierhosts. Laprimitivegetpeername rpondlaquestionquiestu? int getpeername(int sockfd, struct sockaddr *addr, int *addrlen); permetderecupererlesinformationssurlhotequisextconnect . onpourraensuiteutiliserinet_ntoapouraffichersonadresseIP. Laprimitivegethostname Rpondlaquestionquisuisje? int gethostname(char *hostname, size_t size); permetdercuprerenargumentlenomdelamachinelocale. ellerenvoie1sierreuret0encasdesuccs. Laprimitivegethosbyname Ellepermetdobtenirunelistedinformationsurunhte. Ellereoitenargumentlenomdelhteet returnunestructurededonnesdetypehostentcontenantdesinformationssurlhte. struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; }; #define h_addr h_addr_list[0] h_name le nom official de lhte h_aliases un tableau de pointeur pointant sur une liste de nom de lhte h_addrtype le type de ladresse de lhte; habituellement AF_INET. h_length la longueur de ladresse en octet h_addr_list tableau de pointeur pointant les adresses IP de lhte h_addr la premire adresse IP dans h_addr_list. GethostbynamerevoieunpointeurNULLencasderreur.

Exempledutilisation: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { struct hostent *h; if (argc != 2) { // error check the command line fprintf(stderr,"usage: getip address\n"); exit(1); } if ((h=gethostbyname(argv[1])) == NULL) { //get the host info herror("gethostbyname"); exit(1); } printf("Host name : %s\n", h->h_name); printf("IP Address : %s\n", inet_ntoa(*((struct in_addr *)h->h_addr))); return 0; } ExempledunserveurTCPconcurrent #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/wait.h> #include <signal.h> #define MYPORT 3490 // the port users will be connecting to #define BACKLOG 10 // how many pending connections queue will hold void sigchld_handler(int s) { wait(NULL); } int main(void) { int sockfd, new_fd; // listen on sock_fd, new connection on new_fd struct sockaddr_in my_addr; // my address information struct sockaddr_in their_addr; // connectors address information int sin_size; struct sigaction sa; int yes=1; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); }

6
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 bzero(&(my_addr.sin_zero), 8); // zero the rest of the struct if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; // reap all dead processes sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } while(1) { // main accept() loop sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); if (!fork()) { // this is the child process close(sockfd); // child doesnt need the listener if (read(new_fd, "Hello, world!\n", 14, 0) == -1) perror("send"); close(new_fd); exit(0); } close(new_fd); // parent doesnt need this } return 0; } ExempledunclientTCPsimple #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define PORT 3490 // the port client will be connecting to #define MAXDATASIZE 1024 // max number of bytes we can get at once

7
int main(int argc, char *argv[]) { int sockfd, numbytes; char buf[MAXDATASIZE]; struct hostent *he; struct sockaddr_in their_addr; // connectors address information if (argc != 2) { fprintf(stderr,"usage: client hostname\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { // get the host info perror("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } their_addr.sin_family = AF_INET; // host byte order their_addr.sin_port = htons(PORT); // short, network byte order their_addr.sin_addr = *((struct in_addr *)he->h_addr); bzero(&(their_addr.sin_zero), 8); // zero the rest of the struct if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) { perror("connect"); exit(1); } gets(buf); if ((numbytes=send(sockfd, buf, MAXDATASIZE, 0)) == -1) { perror("recv"); exit(1); } buf[numbytes] = \0; printf("Received: %s",buf); close(sockfd); return 0; } ExempledunserveurUDP #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define MYPORT 4950 // the port users will be connecting to #define MAXBUFLEN 100 int main(void) { 27 Beejs Guide to Network Programming int sockfd; struct sockaddr_in my_addr; // my address information struct sockaddr_in their_addr; // connectors address information

8
int addr_len, numbytes; char buf[MAXBUFLEN]; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); 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 bzero(&(my_addr.sin_zero), 8); // zero the rest of the struct if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } addr_len = sizeof(struct sockaddr); if ((numbytes=recvfrom(sockfd,buf,MAXBUFLEN,0, (struct sockaddr *)&their_addr, &addr_len)) == -1) { perror("recvfrom"); exit(1); } printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr)); printf("packet is %d bytes long\n",numbytes); buf[numbytes] = \0; printf("packet contains \"%s\"\n",buf); close(sockfd); return 0; } ExempledunclientUDP #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #define MYPORT 4950 // the port users will be connecting to int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in their_addr; // connectors address information struct hostent *he; int numbytes; if (argc != 3) { fprintf(stderr,"usage: talker hostname message\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { // get the host info perror("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket");

9
exit(1); } their_addr.sin_family = AF_INET; // host byte order their_addr.sin_port = htons(MYPORT); // short, network byte order their_addr.sin_addr = *((struct in_addr *)he->h_addr); bzero(&(their_addr.sin_zero), 8); // zero the rest of the struct if ((numbytes=sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) { perror("recvfrom"); exit(1); } printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr)); close(sockfd); return 0; }

Das könnte Ihnen auch gefallen