| 33 | | |
| 34 | | [[Image(png/client-serveur.png)]] |
| | 33 | |
| | 34 | ** Schéma de principe d'un échange client-serveur avec le protocole TCP (connecté) |
| | 35 | [[Image(htdocs:png/client-serveur.png,300px,nolink)]] |
| | 36 | |
| | 37 | Illustration dans un programme où le client envoie un message à un serveur (qui ne lui répond pas). |
| | 38 | |
| | 39 | ** client.c : |
| | 40 | {{{ |
| | 41 | #!c |
| | 42 | #include <stdio.h> |
| | 43 | #include <stdlib.h> |
| | 44 | #include <unistd.h> |
| | 45 | #include <string.h> |
| | 46 | #include <sys/types.h> |
| | 47 | #include <sys/socket.h> |
| | 48 | #include <netinet/in.h> |
| | 49 | #include <netdb.h> |
| | 50 | |
| | 51 | void error(const char *msg) |
| | 52 | { |
| | 53 | perror(msg); |
| | 54 | exit(0); |
| | 55 | } |
| | 56 | |
| | 57 | int main(int argc, char *argv[]) |
| | 58 | { |
| | 59 | int sockfd, portno, n; |
| | 60 | struct sockaddr_in serv_addr; |
| | 61 | struct hostent *server; |
| | 62 | |
| | 63 | char buffer[256]; |
| | 64 | |
| | 65 | // Le client doit connaitre l'adresse IP du serveur, et son numero de port |
| | 66 | if (argc < 3) { |
| | 67 | fprintf(stderr,"usage %s hostname port\n", argv[0]); |
| | 68 | exit(0); |
| | 69 | } |
| | 70 | portno = atoi(argv[2]); |
| | 71 | |
| | 72 | // 1) Création de la socket, INTERNET et TCP |
| | 73 | |
| | 74 | sockfd = socket(AF_INET, SOCK_STREAM, 0); |
| | 75 | if (sockfd < 0) |
| | 76 | error("ERROR opening socket"); |
| | 77 | |
| | 78 | server = gethostbyname(argv[1]); |
| | 79 | if (server == NULL) { |
| | 80 | fprintf(stderr,"ERROR, no such host\n"); |
| | 81 | exit(0); |
| | 82 | } |
| | 83 | |
| | 84 | // On donne toutes les infos sur le serveur |
| | 85 | |
| | 86 | bzero((char *) &serv_addr, sizeof(serv_addr)); |
| | 87 | serv_addr.sin_family = AF_INET; |
| | 88 | bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); |
| | 89 | serv_addr.sin_port = htons(portno); |
| | 90 | |
| | 91 | // On se connecte. L'OS local nous trouve un numéro de port, grâce auquel le serveur |
| | 92 | // peut nous renvoyer des réponses, le \n permet de garantir que le message ne reste |
| | 93 | // pas en instance dans un buffer d'emission chez l'emetteur (ici c'est le clent). |
| | 94 | |
| | 95 | if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) |
| | 96 | error("ERROR connecting"); |
| | 97 | |
| | 98 | strcpy(buffer,"Coucou Peri\n"); |
| | 99 | n = write(sockfd,buffer,strlen(buffer)); |
| | 100 | |
| | 101 | // On ferme la socket |
| | 102 | |
| | 103 | close(sockfd); |
| | 104 | return 0; |
| | 105 | } |
| | 106 | }}} |
| | 107 | |
| | 108 | ** server.c |
| | 109 | {{{ |
| | 110 | #!c |
| | 111 | #include <string.h> |
| | 112 | #include <unistd.h> |
| | 113 | #include <sys/types.h> |
| | 114 | #include <sys/socket.h> |
| | 115 | #include <netinet/in.h> |
| | 116 | |
| | 117 | #include <netdb.h> |
| | 118 | #include <arpa/inet.h> |
| | 119 | |
| | 120 | |
| | 121 | void error(const char *msg) |
| | 122 | { |
| | 123 | perror(msg); |
| | 124 | exit(1); |
| | 125 | } |
| | 126 | |
| | 127 | int main(int argc, char *argv[]) |
| | 128 | { |
| | 129 | int sockfd, newsockfd, portno; |
| | 130 | socklen_t clilen; |
| | 131 | char buffer[256]; |
| | 132 | struct sockaddr_in serv_addr, cli_addr; |
| | 133 | int n; |
| | 134 | |
| | 135 | if (argc < 2) { |
| | 136 | fprintf(stderr, "ERROR, no port provided\n"); |
| | 137 | exit(1); |
| | 138 | } |
| | 139 | |
| | 140 | // 1) on crée la socket, SOCK_STREAM signifie TCP |
| | 141 | |
| | 142 | sockfd = socket(AF_INET, SOCK_STREAM, 0); |
| | 143 | if (sockfd < 0) |
| | 144 | error("ERROR opening socket"); |
| | 145 | |
| | 146 | // 2) on réclame au noyau l'utilisation du port passé en paramètre |
| | 147 | // INADDR_ANY dit que la socket va être affectée à toutes les interfaces locales |
| | 148 | |
| | 149 | bzero((char *) &serv_addr, sizeof(serv_addr)); |
| | 150 | portno = atoi(argv[1]); |
| | 151 | serv_addr.sin_family = AF_INET; |
| | 152 | serv_addr.sin_addr.s_addr = INADDR_ANY; |
| | 153 | serv_addr.sin_port = htons(portno); |
| | 154 | if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) |
| | 155 | error("ERROR on binding"); |
| | 156 | |
| | 157 | |
| | 158 | // On commence à écouter sur la socket. Le 5 est le nombre max |
| | 159 | // de connexions pendantes |
| | 160 | |
| | 161 | listen(sockfd, 5); |
| | 162 | while (1) { |
| | 163 | newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); |
| | 164 | if (newsockfd < 0) |
| | 165 | error("ERROR on accept"); |
| | 166 | |
| | 167 | bzero(buffer, 256); |
| | 168 | n = read(newsockfd, buffer, 255); |
| | 169 | if (n < 0) |
| | 170 | error("ERROR reading from socket"); |
| | 171 | |
| | 172 | printf("Received packet from %s:%d\nData: [%s]\n\n", |
| | 173 | inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), |
| | 174 | buffer); |
| | 175 | |
| | 176 | close(newsockfd); |
| | 177 | } |
| | 178 | |
| | 179 | close(sockfd); |
| | 180 | return 0; |
| | 181 | } |
| | 182 | }}} |
| | 183 | |