Programmation Socket: UDP Client-Serveur en C

Je suis en train d'écrire un serveur de client de programme en utilisant UDP, et d'attendre-et-stop, mais je n'ai pas à cette partie, je suis encore à essayer de comprendre comment les deux processus (client et serveur) communiquer, parce que sur mon programme client, l'utilisateur doit entrer le nom du serveur ou adresse IP et un nom de port, puis envoyer une expression que le serveur doit calculer. Cependant, j'ai creusé quelques tutoriels sur internet et après codage en conséquence (ou je le croyais) que je ne peux pas faire que le client communique avec le serveur. Ci-dessous mon code, merci de m'éclairer ce que je fais mal, si c'est le bind(), sendto(), recvfrom() ou socket(), ou la totalité d'entre eux. Je ne vois pas quel est exactement le problème. Je sais que le côté client ne faut pas courir sur une boucle infinie, mais jusqu'à présent, je veux faire les programmes de communiquer les uns avec les autres, par la suite, je vais polonais de mon code. Merci!

code côté client:

#include <stdio.h>      //Default System Calls
#include <stdlib.h>     //Needed for OS X
#include <string.h>     //Needed for Strlen
#include <sys/socket.h> //Needed for socket creating and binding
#include <netinet/in.h> //Needed to use struct sockaddr_in
#include <time.h>       //To control the timeout mechanism
#define EXPR_SIZE   1024
#define BUFLEN      512
#define TRUE        1
#define FALSE       0
#define SERVERLEN   1024
int main(int argc, char **argv){
long portNum;           //Since it's possible to input a value bigger
//than 65535 we'll be using long to
//avoid overflows
char expr[EXPR_SIZE];
char server[SERVERLEN];
int fd;                 //file descriptor for the connected socket
int buf[512];
struct hostent *h;           //information of the host
unsigned int addrLen;        //address length after getting the port number
struct sockaddr_in myaddr;   //address of the client
struct sockaddr_in servaddr; //server's address
unsigned int exprLen;
socklen_t slen = sizeof(servaddr);
printf("Enter server name or IP address:");
scanf("%s",server);
printf("Enter port:");
scanf("%ld",&portNum);
if ((portNum < 0) || (portNum > 65535)) {
printf("Invalid port number. Terminating.");
return 0;
}
printf("Enter expression:");
scanf("%s",expr);
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){
perror("cannot bind");
return 0;
}
/*
//Discovering the port number the OS allocated
addrLen = sizeof(myaddr);
if(getsockname(fd, (struct sockaddr *)&myaddr, &addrLen) < 0){
perror("cannot getsockname");
return 0;
}
printf("local port number = %d\n", ntohs(myaddr.sin_port));
*/
memset((char*)&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htonl(portNum);
exprLen = sizeof(expr);
while(TRUE){
printf("Sending message to %s port %ld\n",server, portNum);
if (sendto(fd, expr, strlen(expr), 0, (struct sockaddr *)&servaddr, slen) < 0) {
perror("cannot sendto()");
}
printf("Success\n");
}
return 0;
}

Code côté serveur:

#include <stdio.h>      //Default System Calls
#include <stdlib.h>     //Needed for OS X
#include <string.h>     //Needed for Strlen
#include <sys/socket.h> //Needed for socket creating and binding
#include <netinet/in.h> //Needed to use struct sockaddr_in
#include <time.h>       //To control the timeout mechanism
#define EXPR_SIZE   1024
#define BUFLEN      512
#define TRUE        1
#define SERVERLEN   1024
int main(int argc, char **argv){
struct sockaddr_in myaddr;  //address of the server
struct sockaddr_in claddr;  //address of the client
char buf[BUFLEN];
int fd;
long recvlen;
socklen_t clientlen;
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){
perror("cannot bind");
return 0;
}
clientlen = sizeof(claddr);
while (TRUE) {
recvlen = recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *)&claddr, &clientlen);
if (recvlen < 0) {
perror("cannot recvfrom()");
return 0;
}
printf("Received %ld bytes\n",recvlen);
buf[recvlen] = 0;
printf("Received message: \"%s\"\n",buf);
}
return 0;
}

Le programme serveur n'a pas de sortie de rien, tandis que le client sorties jusqu'à ce que le processus est interrompu:

Enter server name or IP address:127.0.0.1
Enter port:30
Enter expression:2+2
Sending message to 127.0.0.1 port 30
cannot sendto(): Can't assign requested address

J'ai essayé de changer le nom de serveur est localhost, et d'autres ports, mais en vain.

"Je ne peux pas faire que le client communique avec le serveur". Pourrais tu être un peu précis que ça? Le plantage du programme, elle ne produit pas de sortie, est-il produire de la mauvaise sortie? etc. Également inclure le débogage des résultats que vous avez déjà recueillie.
Votre client doit envoyer le même port que le serveur lié.
pour cette ligne de client: scanf("%s",server); il n'y a pas de nombre maximum de caractères d'entrée modificateur sur le "%s " spécificateur de format. Par conséquent, l'utilisateur peut de dépassement de la mémoire tampon d'entrée, résultant en un comportement indéterminé et peut conduire à une seg fault événement. Suggérer: scanf("%1023s",server);
la compilation du logiciel client les résultats dans plusieurs des messages d'avertissement sur les paramètres inutilisés inutilisés variable, jeu de variables, mais pas utilisé, etc. Un bon départ sur la fixation de toutes ces mises en garde serait de remplacer la fonction main() signature avec int main( void )
lors de l'appel de la plupart des fonctions du système, par exemple scanf(), toujours vérifier la valeur retournée (pas la valeur du paramètre) pour assurer l'opération a été un succès.

OriginalL'auteur William Studart | 2016-02-23